设计模式之装饰者设计模式
1.定义:动态的将责任附加到对象上。想要扩展功能,装饰者是有别于继承的另外一种选择。就增加功能而言,装饰者模式比子类更加的灵活
涉及到的设计原则:类应该对扩展开放,对修改关闭
要点:1.装饰者和被装饰者有相同的超类型
2.可以用一个或者多个装饰者包装一个对象
3.既然装饰者和被装饰者有相同的超类型,所以在任何需要原始对象的场合,就可以使用装饰过的对象代替它
4.装饰者可以在所委托的被装饰者之前或者之后,添加自己的行为,已达到特定的目的
2.装饰者模式的重要组件
包含4个:Component抽象组件、ConcreteComponent具体构件、Decorate装饰角色、ConcreteDecorateA具体的装饰角色
Component抽象组件:可以是一个接口或者抽象类,就是定义我们最原始的对象
ConcreteComponent具体构件:是Component抽象组件的实现。也是要装饰的对象
Decorate装饰角色:一般是一个抽象类,实现接口或者抽象方法,它里面不一样有抽象的方法,但是里面必会有一个变量指向Component抽象构件
ConcreteDecorate具体的装饰角色: 具体的装饰类,就是要装饰最原始对象的类
3.装饰者模式基本类图
基本代码:
1.Component抽象组件
public abstract class Component { // 要抽象的方式 public abstract void operate(); }
2.ConcreteComponent具体构件
public class ConcreteComponent extends Component { // 具体的实现 @Override public void operate() { System.out.println("做一些事情"); } }
3.Decorate装饰角色
public class Decorate extends Component { private Component component = null; // 通过构造函数传递被装饰者 public Decorate(Component component) { this.component = component; } // 委托给被装饰者执行 @Override public void operate() { this.component.operate(); } }
4.ConcreteDecorate具体的装饰A角色
public class ConcreteDecorateA extends Decorate { // 定义被装饰者 public ConcreteDecorateA(Component component) { super(component); } // 定义自己的修饰方法 public void method1() { System.out.println("方法1修饰"); } @Override public void operate() { super.operate(); this.method1(); } }
ConcreteDecorate具体的装饰B角色
public class ConcreteDecorateB extends Decorate { // 定义被装饰者 public ConcreteDecorateB(Component component) { super(component); } // 定义自己的修饰方法 public void method1() { System.out.println("方法2修饰"); } @Override public void operate() { super.operate(); this.method1(); } }
5.测试类
public class TestMain { @Test public void decorateDesignTest() { Component component = new ConcreteComponent(); // 第一次修饰 component = new ConcreteDecorateA(component); //第二次修饰 component = new ConcreteDecorateB(component); //修饰后执行 component.operate(); } }
4.装饰者设计模式案例:
90级封号斗罗,附加魂环
1.创建一个魂师类(最原始的对象,也就是Component抽象组件)
public interface HunShi { String getDescription(); int getHunShiLevel(); }
2.创建一个具体的对象(相当于ConcreteComponent组件)
public class FengHaoDouLuo implements HunShi { @Override public String getDescription() { return "封号斗罗"; } @Override public int getHunShiLevel() { return 0; } }
3.创建一个装饰者的抽象组件(相当于Decorate抽象组件)
public abstract class HunLoop implements HunShi { }
可以在这一层,组合被装饰者
4.创建具体的装饰者(相当于ConcreteDecorate组件)
1.创建十年魂环
public class TenYearHunLoop extends HunLoop { HunShi hunShi; public TenYearHunLoop(HunShi hunShi) { this.hunShi = hunShi; } @Override public String getDescription() { return hunShi.getDescription()+"白"; } @Override public int getHunShiLevel() { return hunShi.getHunShiLevel()+10; } }
2.创建百年魂环
public class BaiYearHunLoop extends HunLoop { private HunShi hunShi; public BaiYearHunLoop(HunShi hunShi) { this.hunShi = hunShi; } @Override public String getDescription() { return hunShi.getDescription()+"黄"; } @Override public int getHunShiLevel() { return hunShi.getHunShiLevel()+10; } }
3.创建千年魂环
public class QianYearHunLoop extends HunLoop { HunShi hunShi; public QianYearHunLoop(HunShi hunShi) { this.hunShi = hunShi; } @Override public String getDescription() { return hunShi.getDescription()+"紫"; } @Override public int getHunShiLevel() { return hunShi.getHunShiLevel()+10; } }
4.创建万年魂环
public class WangYearHunLoop extends HunLoop { HunShi hunShi; public WangYearHunLoop(HunShi hunShi) { this.hunShi = hunShi; } @Override public String getDescription() { return hunShi.getDescription()+"黑"; } @Override public int getHunShiLevel() { return hunShi.getHunShiLevel()+10; } }
5.创建10万年魂环
public class TenWangYearHunLoop extends HunLoop { HunShi hunShi; public TenWangYearHunLoop(HunShi hunShi) { this.hunShi = hunShi; } @Override public String getDescription() { return hunShi.getDescription()+"红"; } @Override public int getHunShiLevel() { return hunShi.getHunShiLevel()+10; } }
6.创建一个魂骨
public class BaZhuMaoHunGu implements HunShi { private HunShi hunShi; public BaZhuMaoHunGu(HunShi hunShi) { this.hunShi = hunShi; } @Override public String getDescription() { return hunShi.getDescription()+"八蛛魂骨"; } @Override public int getHunShiLevel() { return hunShi.getHunShiLevel(); } }
5.创建一个测试类
@Test public void test001() { // 创建一个普通的封号斗罗 HunShi hunShi = new FengHaoDouLuo(); // 为封号斗罗添加魂环 hunShi = new TenYearHunLoop(hunShi); hunShi = new BaiYearHunLoop(hunShi); hunShi = new BaiYearHunLoop(hunShi); hunShi = new QianYearHunLoop(hunShi); hunShi = new QianYearHunLoop(hunShi); hunShi = new WangYearHunLoop(hunShi); hunShi = new WangYearHunLoop(hunShi); hunShi = new WangYearHunLoop(hunShi); hunShi = new TenWangYearHunLoop(hunShi); log.info(hunShi.getDescription()); // 添加外魂附骨 hunShi = new BaZhuMaoHunGu(hunShi); System.out.println( hunShi.getDescription()); System.out.println("等级"+hunShi.getHunShiLevel()); }
运行结果,如下图所示:
6.装饰者模式的优点
1.装饰者类和被装饰者类可以独立发展,不会相互耦合
2.装饰者模式是继承的一种替代方案,我们不管装饰多少层,返回的对象还是Component原始对象类型。
3.继承是静态的给类添加功能,而装饰者设计模式是动态的给类添加功能
4.扩展性非常好
7.装饰者模式的缺点:
1.装饰者模式如果装饰多层,那么类是比较复杂的。如果内层报错了,就比较麻烦。因此,应减少类的数量,以降低系统的复杂度
8.装饰者模式的使用场景:
1.需要扩展一个类的功能,或者给一个类附加功能
2.需要给一个对象添加功能,这些功能,可以动态的进行撤销
3.需要给一批的兄弟类加装功能的时候,当然首选装饰者模式,比如JDK的IO流,就是典型的装饰者设计模式