1 package decoration; 2 3 /**@author cby 4 * 装饰模式模板 5 * 装饰模式: 6 * 动态地给一个对象添加一些额外的职责,就增强功能来说,装饰模式比生成子类更为灵活 7 * 8 * 总结:一个非常巧妙的设计模式,正如它的名字:装饰模式 9 * 我们在穿一件衣服的时候是会按照一种顺序来穿的,先穿内裤再穿外裤 10 * 如果反着来的话就不对了(超人除外) 11 * 而这种设计模式正体现了这种要求有顺序的方法 12 * 13 * 几个细节: 14 * 我们为什么可以确保顺序呢,因为在ConcreteDecorator的operation方法里面我们调用的 15 * 是父类的operation方法,然后再调用自己的独特的方法。 16 * Decorator类中的setComponent方法是用来设置传入的真正对象的,用来在operation中调用 17 * 比如说这里 我们调用的是d2的operation方法,d2再去调用父类的operation方法,而父类中传入的 18 * 是d1对象,所以调用的是d1的operation方法,d1再去调用父类的operation方法,而它的父类中 19 * 传入的是ConcreteComponent的对象,所以调用的是ConcreteComponent对象的方法后再调用 20 * d1本身的方法,再调用d2本身的方法 21 * 所以我们在main函数中只调用了一个对象的operation方法,但是却出现了三行字, 22 * 顺序和我们setComponent的顺序一致 23 * 可以说是非常的巧妙了 24 * 25 */ 26 27 /**定义了一个对象接口,可以动态添加职责 28 * 29 */ 30 abstract class Component 31 { 32 public abstract void operation(); 33 } 34 35 class ConcreteComponent extends Component 36 { 37 @Override 38 public void operation() { 39 System.out.println("具体对象的操作"); 40 } 41 } 42 43 public abstract class DecorationTemplate extends Component{ 44 protected Component component; 45 46 /** 47 * 设置component,体现了多态 48 * 49 */ 50 public void setComponent(Component component) 51 { 52 this.component = component; 53 } 54 55 /** 56 * 重写了operation() 实际执行的是component的operation 57 * 58 */ 59 @Override 60 public void operation() { 61 if(component != null) 62 { 63 component.operation(); 64 } 65 } 66 } 67 class ConcreteDecoratorA extends DecorationTemplate 68 { 69 /** 70 * 本类独有的功能,用于区别ConcreteDecoratorB 71 */ 72 private String addedState; 73 74 @Override 75 public void operation() { 76 super.operation(); 77 addedState = "New State"; 78 System.out.println("具体装饰对象A的操作"); 79 } 80 } 81 82 class ConcreteDecoratorB extends DecorationTemplate 83 { 84 @Override 85 public void operation() { 86 super.operation(); 87 addedBehavior(); 88 System.out.println("具体装饰对象B的操作"); 89 } 90 91 private void addedBehavior() 92 { 93 94 } 95 }
main函数:
ConcreteComponent c =new ConcreteComponent(); ConcreteDecoratorA d1 = new ConcreteDecoratorA(); ConcreteDecoratorB d2 = new ConcreteDecoratorB(); d1.setComponent(c); d2.setComponent(d1); d2.operation();
控制台输出:
具体对象的操作
具体装饰对象A的操作
具体装饰对象B的操作
这个模式在调用operation方法的时候特别的复杂,一定要好好体会,多看几遍!
下面我来举一个具体的例子:穿衣服
1 package decoration; 2 3 /** 4 * @author cby 5 * 学习设计模式要善于变通,如果只有一个ConcreteComponent类而没有抽象的Component类 6 * 那么Decorator就可以是ConcreteComponent的一个子类。 7 * 同样道理,如果只有一个ConcreteDecorator类,那就没有必要建立一个单独的Decorator类 8 * 而可以把Decorator和ConcreteDecorator的责任合并成一个类 9 */ 10 11 class Person 12 { 13 private String name; 14 public Person() 15 {} 16 public Person(String name) 17 { 18 this.name = name; 19 } 20 21 public void show() 22 { 23 System.out.println("人类高质量" + this.name); 24 } 25 } 26 27 public class DecorationExample extends Person 28 { 29 protected Person component; 30 31 public void Decorate(Person component) 32 { 33 this.component = component; 34 } 35 36 @Override 37 public void show() 38 { 39 if(component != null) 40 { 41 component.show(); 42 } 43 } 44 } 45 class Suit extends DecorationExample 46 { 47 @Override 48 public void show() { 49 System.out.print("西装 "); 50 super.show(); 51 } 52 } 53 54 class Tie extends DecorationExample 55 { 56 @Override 57 public void show() { 58 System.out.print("领带 "); 59 super.show(); 60 } 61 } 62 63 class LeatherShoes extends DecorationExample{ 64 @Override 65 public void show() { 66 System.out.print("皮鞋 "); 67 super.show(); 68 } 69 } 70 71 class Trouser extends DecorationExample{ 72 @Override 73 public void show() { 74 System.out.print("西裤 "); 75 super.show(); 76 } 77 }
main函数:
public static void main(String[] args) { Person cby = new Person("cby"); LeatherShoes leatherShoes = new LeatherShoes(); Trouser trouser = new Trouser(); Tie tie = new Tie(); Suit suit = new Suit(); leatherShoes.Decorate(cby); trouser.Decorate(leatherShoes); tie.Decorate(trouser); suit.Decorate(tie); suit.show(); }
控制台输出:
西装 领带 西裤 皮鞋 人类高质量cby
让我来细细拆分研究代码:
leatherShoes.Decorate(cby);
在实例化对象之后我们就正式开始装饰了,首先我们把leathershoes对象中的component赋成cby
然后继续赋值
trouser.Decorate(leatherShoes);
tie.Decorate(trouser);
suit.Decorate(tie);
赋值完成之后开始调用,然后关键的点就来了
suit.show();
我们调用suit的show方法,他会首先打印西装,再去调用父类中的show方法
class Suit extends DecorationExample { @Override public void show() { System.out.print("西装 "); super.show(); } }
我们再去找他的父类DecorationExample就可以发现这个类调用的是类中Person类型的成员component的show方法
而我们之前设置过这个component了,就是tie,于是tie再去调用show方法。
同理首先打印领带,再调用trouser对象的show方法,这样循环下去
一直到cby,调用cby的show方法,而cby的show方法是打印 "人类高质量cby"
就结束了
这就是全过程