装饰模式Decorator
1.1 什么是装饰模式?
装饰模式Decorator,动态的给一些对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活
1.2装饰模式Decorator的结构图
Component是定义一个对象接口,可以给这些对象动态的添加职责.
ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责.
Decorator装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需
知道Decorator的存在的,至于ConcretDecorator就是具体的装饰对象,起到给Component添加职责的功能
1.3 代码实现
Component类
1 package dp06Decorator02; 2 3 public interface Component { 4 public void operation(); 5 }
ConcreteComponent类
1 package dp06Decorator02; 2 3 public class ConcreteCompnent implements Component { 4 5 public void operation() { 6 System.out.println("具体对象的操作"); 7 8 } 9 10 }
Decorator类
1 package dp06Decorator02; 2 3 public class Decorator implements Component{ 4 5 private Component component; 6 //设置Component 7 public void setComponent(Component component) { 8 this.component = component; 9 } 10 //重写operation(),实际执行的是Component的operation() 11 public void operation() { 12 if(component!=null){ 13 component.operation(); 14 } 15 } 16 17 }
ConcreteComponentA类
1 package dp06Decorator02; 2 3 public class ConcreteDecoratorA extends Decorator { 4 5 private String addState;// 本类的独有功能,以区别于ConcreteDecoratorB 6 7 public void operation() { 8 super.operation(); 9 addState = "new State"; 10 System.out.println("具体装饰对象A的操作"); 11 } 12 13 }
ConcreteComponentB类
1 package dp06Decorator02; 2 3 public class ConcreteDecoratorB extends Decorator { 4 private void addedBehavior() {};// 本类独有的方法,以区别于ConcreteDecoratorA 5 6 public void operation() { 7 super.operation(); 8 addedBehavior(); 9 System.out.println("具体装饰对象B的操作"); 10 } 11 12 }
测试代码Test类
1 package dp06Decorator02; 2 3 public class Test { 4 public static void main(String[] args) { 5 ConcreteCompnent c = new ConcreteCompnent(); 6 ConcreteDecoratorA d1 = new ConcreteDecoratorA(); 7 ConcreteDecoratorB d2 = new ConcreteDecoratorB(); 8 9 d1.setComponent(c); 10 d2.setComponent(d1); 11 d2.operation(); 12 } 13 }
结果
小结:装饰模式是利用setComponent来对对象进行包装,这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能
,不需要关心如何被添加到对象链当中.
当然学习模式要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个
一个子类.同理,如果只有一个ConcreteComponent类.那么就没有必要建立一个单独的Decorator类,而可以把Decorator和
ConcreteComponent的责任合成一个类.
2.1装饰模式实例:人穿衣带帽
代码结构图:
"Person"类,它是Concretecomponent
1 package dp06Decorator02; 2 3 public class Person { 4 5 private String name; 6 public Person(){ 7 8 } 9 public Person(String name){ 10 this.name=name; 11 } 12 public void show(){ 13 System.out.println("装扮的:"+name); 14 } 15 }
服饰类Decorator
1 package dp06Decorator02; 2 3 public class Finery extends Person{ 4 private Person component; 5 //打扮 6 public void decorator(Person component){ 7 this.component=component; 8 } 9 public void show() { 10 if(component!=null){ 11 component.show(); 12 } 13 } 14 }
具体服饰类ConcreteDecorator
1 package dp06Decorator02; 2 3 public class Tshirts extends Finery{ 4 public void show() { 5 System.out.println("大T恤"); 6 super.show(); 7 } 8 }
1 package dp06Decorator02; 2 3 public class BigTrouser extends Finery{ 4 5 public void show() { 6 System.out.println("垮裤"); 7 super.show(); 8 } 9 10 }
其余代码类似,省略
测试代码FineryTest类
package dp06Decorator02; public class FineryTest { public static void main(String[] args) { Person p = new Person("小鸟"); System.out.println("\n第一种装扮:"); Sneakers pqx = new Sneakers();//破球鞋 BigTrouser kk = new BigTrouser();//垮裤 Tshirts dtx = new Tshirts();//T恤 pqx.decorator(p); kk.decorator(pqx); dtx.decorator(kk); dtx.show(); System.out.println("\n第二种装扮:"); LeatherShoes px = new LeatherShoes();//皮鞋 Tie ld = new Tie();//领带 Suit xz = new Suit();//西装 px.decorator(p); ld.decorator(px); xz.decorator(ld); xz.show(); } }
测试结果
2.2装饰模式总结
说白了,装饰模式是为已有功能动态的添加更多功能的一种方式.
什么时候使用装饰模式?
当系统需要新功能的时候,是向旧的类中添加新的代码,这些新加的代码通常装饰了原有类的核心职责或主要行为.比如用西装装饰小鸟,但这种做法的问题在于,他们在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度 ,就像起初的那个'人'类,而这些新加入的东西仅仅是为了满足一些只在某种特定的情况下才会执行的特殊行为的需要.而装饰模式却提供了一个非常好的解决方法,他把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择的 按顺序的使用装饰功能包装对象了.
装饰模式的有点:把类中的装饰功能从类中搬移去除,这样可以简化原有的类,可以有效的把类的核心职责和装饰功能区分开,而且可以去除相关类中重复的装饰逻辑.