装饰器模式:在不改变原文件以及使用继承的情况下,对一个类动态的增加功能。实际上就是创建一个装饰对象,把真实的对象放入装饰对象中,然后进行扩展。
代码实现
前言:举个栗子,我现在就是钢铁侠,现在雷神的弟弟洛基来到了地球。我为了保护地球,必须打败洛基,但是洛基可是诡计之神啊,我想打败他很困难。所以现在我需要对我的马克7号进行改造,在我的马克7号上面添加几种武器,使我的战衣更加强大,才能打败洛基。但是我不能直接把我的战衣拆掉重新改造,如果拆掉再改造再装好,地球都已经毁灭了,我需要直接将武器装在已有的战衣上,这个时候,我们就用到了装饰器模式。
钢铁侠(抽象构件 Component)
@AllArgsConstructor @NoArgsConstructor @Data public abstract class IronMan { private String suitName; public abstract void show(); }
马克7号(具体构件 Concrete Component)
public class Mark7 extends IronMan { @Override public void show() { this.setSuitName("马克7号"); System.out.println("战衣名称:" + this.getSuitName()); } }
改造类(抽象装饰 Decorator)
public abstract class Remould extends IronMan { private IronMan ironMan; public void remould(IronMan ironMan) { this.ironMan = ironMan; } @Override public void show() { if (ironMan != null) { ironMan.show(); } } }
电弧脉冲炮(具体装饰 Concrete Decorator)
public class ArcPulseGun extends Remould { @Override public void show() { super.show(); System.out.println("名称:电弧脉冲炮,描述:发射一种双效功能的非杀伤电弧型刺激弹"); } }
集束炮(具体装饰 Concrete Decorator)
public class ClusterGun extends Remould { @Override public void show() { super.show(); System.out.println("名称:集束炮,描述:集束炮是集中于胸部一点的直线型远距离攻击,画面上常表现为一束高能、密集、持续的粒子流"); } }
激光武器(具体装饰 Concrete Decorator)
public class LaserWeapons extends Remould { @Override public void show() { super.show(); System.out.println("名称:激光武器,描述:用高能的激光对远距离的目标进行精确射击或用于防御导弹等的武器"); } }
测试类
public class DecoratorTest { public static void main(String[] args) { IronMan ironMan = new Mark7(); System.out.println("改进战衣"); ArcPulseGun arcPulseGun = new ArcPulseGun(); arcPulseGun.remould(ironMan); ClusterGun clusterGun = new ClusterGun(); clusterGun.remould(arcPulseGun); LaserWeapons laserWeapons = new LaserWeapons(); laserWeapons.remould(clusterGun); laserWeapons.show(); } }
结果
改进战衣 战衣名称:马克7号 名称:电弧脉冲炮,描述:发射一种双效功能的非杀伤电弧型刺激弹 名称:集束炮,描述:集束炮是集中于胸部一点的直线型远距离攻击,画面上常表现为一束高能、密集、持续的粒子流 名称:激光武器,描述:用高能的激光对远距离的目标进行精确射击或用于防御导弹等的武器
源码分析
对于io流,基本上就是用的此设计模式,对于基本的文件输入流,可以在包裹一层缓冲流。
DataInputStream dis = new DataInputStream(new FileInputStream("c:\\decorator.txt"));
可以看到FileInputStream是被增强的对象,然后DataInputStream是装饰类,在装饰类中可以放入被增强对象,然后对其进行增强。
优缺点
优点:
通过使用不同的具体装饰类以及这些装饰类的排列组合,动态的方式来扩展一个对象的功能。
相比于继承,装饰器模式可以提供比继承更多的灵活性。
缺点:
使用装饰器模式会产生比使用继承关系更多的对象,多层装饰比较复杂。