Java 设计模式西游篇 - 第五回:装饰者模式添法力 悟空披挂新战袍

诗曰:

复制代码
法宝威力需增强,继承子类太繁琐。
装饰者模式来相助,动态添法显神通。

📖 故事

话说师徒四人来到"法力增强山",悟空觉得金箍棒威力不够,想要增强法力。

悟空愁道:"师父,这山的妖怪厉害,俺老孙的金箍棒威力不够啊!"

唐僧道:"悟空,你可有法子增强法力?"

悟空挠头:"徒儿倒是想过,要么打造一把新棒子,要么给金箍棒附魔。可要是每种附魔都要打造新棒子,那不得累死俺老孙!"

🐉 踩坑打怪:继承爆炸之劫

第一劫:类爆炸

悟空想了个笨办法:

java 复制代码
// 基础金箍棒
public class GoldenCudgel {
    public void attack() {
        System.out.println("金箍棒 - 普通攻击!");
    }
}

// 火焰金箍棒
public class FireGoldenCudgel extends GoldenCudgel {
    @Override
    public void attack() {
        super.attack();
        System.out.println("附加火焰伤害!");
    }
}

// 冰冻金箍棒
public class IceGoldenCudgel extends GoldenCudgel {
    @Override
    public void attack() {
        super.attack();
        System.out.println("附加冰冻伤害!");
    }
}

// 雷电金箍棒
public class ThunderGoldenCudgel extends GoldenCudgel {
    @Override
    public void attack() {
        super.attack();
        System.out.println("附加雷电伤害!");
    }
}

// 火焰 + 冰冻金箍棒
public class FireIceGoldenCudgel extends GoldenCudgel {
    @Override
    public void attack() {
        super.attack();
        System.out.println("附加火焰伤害!");
        System.out.println("附加冰冻伤害!");
    }
}

// 火焰 + 雷电金箍棒...
// 冰冻 + 雷电金箍棒...
// 火焰 + 冰冻 + 雷电金箍棒...

八戒惊呼: "猴哥!你这得有几十种组合啊!每加一种附魔,就要多好几个类!"

悟空怒道: "正是!这'继承爆炸'太坑了!俺老孙得想个巧法子!"

⚔️ 装饰者模式大法

第一步:定义组件接口
java 复制代码
// 武器接口
public interface Weapon {
    void attack();
    int getDamage();
}
第二步:实现具体组件
java 复制代码
// 基础金箍棒
public class GoldenCudgel implements Weapon {
    @Override
    public void attack() {
        System.out.println("金箍棒 - 普通攻击!");
    }
    
    @Override
    public int getDamage() {
        return 100;
    }
}
第三步:实现装饰者基类
java 复制代码
// 装饰者基类
public abstract class WeaponDecorator implements Weapon {
    protected Weapon weapon; // 持有一个武器引用
    
    public WeaponDecorator(Weapon weapon) {
        this.weapon = weapon;
    }
    
    @Override
    public void attack() {
        weapon.attack(); // 委托给被装饰的武器
    }
    
    @Override
    public int getDamage() {
        return weapon.getDamage();
    }
}
第四步:实现具体装饰者
java 复制代码
// 火焰附魔装饰者
public class FireEnchantDecorator extends WeaponDecorator {
    public FireEnchantDecorator(Weapon weapon) {
        super(weapon);
    }
    
    @Override
    public void attack() {
        weapon.attack();
        System.out.println("附加火焰伤害!🔥");
    }
    
    @Override
    public int getDamage() {
        return weapon.getDamage() + 20;
    }
}

// 冰冻附魔装饰者
public class IceEnchantDecorator extends WeaponDecorator {
    public IceEnchantDecorator(Weapon weapon) {
        super(weapon);
    }
    
    @Override
    public void attack() {
        weapon.attack();
        System.out.println("附加冰冻伤害!❄️");
    }
    
    @Override
    public int getDamage() {
        return weapon.getDamage() + 15;
    }
}

// 雷电附魔装饰者
public class ThunderEnchantDecorator extends WeaponDecorator {
    public ThunderEnchantDecorator(Weapon weapon) {
        super(weapon);
    }
    
    @Override
    public void attack() {
        weapon.attack();
        System.out.println("附加雷电伤害!⚡");
    }
    
    @Override
    public int getDamage() {
        return weapon.getDamage() + 25;
    }
}

// 吸血附魔装饰者
public class LifestealDecorator extends WeaponDecorator {
    public LifestealDecorator(Weapon weapon) {
        super(weapon);
    }
    
    @Override
    public void attack() {
        weapon.attack();
        System.out.println("附加吸血效果!🩸");
    }
    
    @Override
    public int getDamage() {
        return weapon.getDamage() + 10;
    }
}
第五步:实战演练
java 复制代码
public class Main {
    public static void main(String[] args) {
        // 基础金箍棒
        Weapon cudgel = new GoldenCudgel();
        System.out.println("=== 基础金箍棒 ===");
        cudgel.attack();
        System.out.println("伤害:" + cudgel.getDamage());
        
        // 火焰金箍棒
        System.out.println("\n=== 火焰金箍棒 ===");
        Weapon fireCudgel = new FireEnchantDecorator(new GoldenCudgel());
        fireCudgel.attack();
        System.out.println("伤害:" + fireCudgel.getDamage());
        
        // 火焰 + 冰冻金箍棒
        System.out.println("\n=== 火焰 + 冰冻金箍棒 ===");
        Weapon fireIceCudgel = new IceEnchantDecorator(
            new FireEnchantDecorator(new GoldenCudgel())
        );
        fireIceCudgel.attack();
        System.out.println("伤害:" + fireIceCudgel.getDamage());
        
        // 火焰 + 冰冻 + 雷电金箍棒
        System.out.println("\n=== 火焰 + 冰冻 + 雷电金箍棒 ===");
        Weapon ultimateCudgel = new ThunderEnchantDecorator(
            new IceEnchantDecorator(
                new FireEnchantDecorator(new GoldenCudgel())
            )
        );
        ultimateCudgel.attack();
        System.out.println("伤害:" + ultimateCudgel.getDamage());
        
        // 终极形态:全附魔 + 吸血
        System.out.println("\n=== 终极形态:全附魔 + 吸血 ===");
        Weapon godCudgel = new LifestealDecorator(
            new ThunderEnchantDecorator(
                new IceEnchantDecorator(
                    new FireEnchantDecorator(new GoldenCudgel())
                )
            )
        );
        godCudgel.attack();
        System.out.println("伤害:" + godCudgel.getDamage());
    }
}

输出:

复制代码
=== 基础金箍棒 ===
金箍棒 - 普通攻击!
伤害:100

=== 火焰金箍棒 ===
金箍棒 - 普通攻击!
附加火焰伤害!🔥
伤害:120

=== 火焰 + 冰冻金箍棒 ===
金箍棒 - 普通攻击!
附加火焰伤害!🔥
附加冰冻伤害!❄️
伤害:135

=== 火焰 + 冰冻 + 雷电金箍棒 ===
金箍棒 - 普通攻击!
附加火焰伤害!🔥
附加冰冻伤害!❄️
附加雷电伤害!⚡
伤害:160

=== 终极形态:全附魔 + 吸血 ===
金箍棒 - 普通攻击!
附加火焰伤害!🔥
附加冰冻伤害!❄️
附加雷电伤害!⚡
附加吸血效果!🩸
伤害:170

🏆 战斗总结

悟空得意: "哈哈!俺老孙这装饰者模式,想加什么附魔就加什么,不用打造新棒子!"

八戒问: "猴哥,这和继承有啥区别?"

悟空答: "呆子,听好了------"

对比项 继承 装饰者模式
类数量 组合爆炸 线性增长
灵活性 编译时固定 运行时动态组合
扩展性 改代码 加新装饰者
职责 容易混杂 单一职责

本章要点

要点 说明
核心思想 动态地给对象添加职责,继承的替代方案
适用场景 需要动态添加功能、避免类爆炸
优点 灵活组合、符合开闭原则、单一职责
缺点 装饰者过多会增加复杂度、调试困难

下回预告

话说师徒继续西行,来到"真假美猴王岭"。两个悟空一模一样,如何辨别?且看代理模式如何设关卡!

欲知后事如何,且听第六回分解!


相关推荐
xieliyu.40 分钟前
Java算法精讲:双指针(三)
java·开发语言·算法
明夜之约1 小时前
Spring Boot 自动装配源码
java·spring boot·后端
Leaton Lee1 小时前
Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程
java·spring boot·后端·架构
Jinkxs1 小时前
Resilience4j- 与 Spring Boot 快速集成:自动配置与基础注解使用
java·spring boot·后端
辣机小司1 小时前
【踩坑记录:Spring Boot 配置文件读取值不一致?警惕 YAML 的“八进制陷阱”与 SnakeYAML 版本之谜】
java·spring boot·后端·yaml·踩坑记录
fangdengfu1232 小时前
ES分析系统各个服务日志占用量
java·前端·elasticsearch
云烟成雨TD2 小时前
Spring AI 1.x 系列【51】可观测性技术选型
java·人工智能·spring
星越华夏2 小时前
ESP32-CAM图像传输项目说明文档
java·后端·struts·esp32
Jinkxs3 小时前
Java 跨域14-Java 与区块链(Hyperledger)集成
java·开发语言·区块链
晨曦中的暮雨4 小时前
Golang速通(Javaer版)
java·开发语言·后端·golang