Java学习笔记——设计模式之三.装饰模式
函数应该做一件事,做好这件事,只做这一件事。
——Clean Code
装饰模式,上代码:
先定义零件类:
1 package cn.no3.decorator.template; 2 3 public abstract class Component { 4 5 public abstract void operation(); 6 }
再定义具体零件类(即被装饰类)继承零件类:
1 package cn.no3.decorator.template; 2 3 public class ConcreteComponent extends Component{ 4 5 @Override 6 public void operation() { 7 // TODO Auto-generated method stub 8 System.out.println("对一个Object进行装饰:"); 9 } 10 11 }
然后定义装饰类,继承零件类:
1 package cn.no3.decorator.template; 2 3 public class Decorator extends Component { 4 5 protected Component component; 6 7 public void setComponent(Component component) { 8 this.component = component; 9 } 10 11 @Override 12 public void operation() { 13 //调用的是传入component的operation方法 14 if (component != null) { 15 component.operation(); 16 } 17 18 } 19 20 }
定义装饰类的子类:
1 package cn.no3.decorator.template; 2 3 public class ConcreteDecoratorA extends Decorator { 4 5 private String addedField; 6 7 @Override 8 public void operation() { 9 // TODO Auto-generated method stub 10 super.operation();//第一行调用super,则从前往后包装.反之则从后往前包装 11 addedField = "新的装饰物A"; 12 System.out.println("装饰了:"+addedField); 13 } 14 } 15 16 public class ConcreteDecoratorB extends Decorator { 17 18 @Override 19 public void operation() { 20 // TODO Auto-generated method stub 21 super.operation(); 22 AddedBehavior(); 23 } 24 25 private void AddedBehavior() { 26 // TODO Auto-generated method stub 27 System.out.println("完成装饰,最后照个相"); 28 } 29 30 }
测试类测试:
1 package cn.no3.decorator.template; 2 3 public class _Test { 4 5 public static void main(String[] args) { 6 //新建装饰对象 7 ConcreteComponent concreteComponent = new ConcreteComponent(); 8 ConcreteDecoratorA concreteDecoratorA = new ConcreteDecoratorA(); 9 ConcreteDecoratorB concreteDecoratorB = new ConcreteDecoratorB(); 10 //逐层包装 11 //如果注掉下句,还是先调用A的super,发现没传component,于是A的super什么都不做 12 concreteDecoratorA.setComponent(concreteComponent);//A先调用cC,cC方法不再调用super. 13 concreteDecoratorB.setComponent(concreteDecoratorA);//B先调用A 14 //输出最终结果 15 concreteDecoratorB.operation(); 16 } 17 }
把这个例子中的Component类换成接口也是一样的:
举个例子:
需求:
定义一个角色,让他实现IWearable接口,
再定义装备实现IWearable接口
人物装备装备.
上代码:
1 package cn.no3.decorator.instance; 2 3 public abstract interface IWearable { 4 5 public abstract void operation(); 6 }
1 package cn.no3.decorator.instance; 2 3 public class Clothes implements IWearable { 4 5 protected IWearable component; 6 7 public void setComponent(IWearable component) { 8 this.component = component; 9 } 10 11 @Override 12 public void operation() { 13 if (component != null) { 14 component.operation(); 15 } 16 17 } 18 19 }
1 package cn.no3.decorator.instance; 2 3 //即使只有一双鞋也要定义父类,否则无法通过对象的super.operation对装饰进行传递 4 public class Shoes implements IWearable { 5 6 protected IWearable component; 7 8 public void setComponent(IWearable component) { 9 this.component = component; 10 } 11 12 @Override 13 public void operation() { 14 if (component != null) { 15 component.operation(); 16 } 17 } 18 19 }
1 package cn.no3.decorator.instance; 2 3 public class Weapons implements IWearable { 4 5 protected IWearable component; 6 7 public void setComponent(IWearable component) { 8 this.component = component; 9 } 10 11 @Override 12 public void operation() { 13 if (component != null) { 14 component.operation(); 15 } 16 17 } 18 19 }
他们的子类都是重写父类operation()方法,最先调用(或者最后调用),super.operation();此处省略若干行
1 package cn.no3.decorator.instance; 2 3 public class WeaponA extends Weapons { 4 5 @Override 6 public void operation() { 7 // TODO Auto-generated method stub 8 super.operation(); 9 System.out.println("装备了:霜之哀伤"); 10 } 11 }
角色类
1 package cn.no3.decorator.instance; 2 3 public class Character implements IWearable{ 4 5 @Override 6 public void operation() { 7 // TODO Auto-generated method stub 8 System.out.println("对一个人物进行装备:"); 9 } 10 11 }
测试类:
1 package cn.no3.decorator.instance; 2 3 public class _Test { 4 5 public static void main(String[] args) { 6 //新建装备对象 7 Character concreteComponent = new Character(); 8 ClotheA fantasyKiller = new ClotheA(); 9 ClotheB bravingArmor = new ClotheB(); 10 WeaponA frostmourne = new WeaponA(); 11 WeaponB DoubleRoses = new WeaponB(); 12 ShoesA shoes = new ShoesA(); 13 //逐层包装 14 fantasyKiller.setComponent(concreteComponent); 15 bravingArmor.setComponent(fantasyKiller); 16 frostmourne.setComponent(bravingArmor); 17 DoubleRoses.setComponent(frostmourne); 18 shoes.setComponent(DoubleRoses);//shoes.setComponent(shoes)会陷入死循环 19 //输出最终结果 20 shoes.operation(); 21 } 22 }
装饰模式是为已有功能动态地添加更多功能的一种方式
装饰模式把每个要装饰的功能放在单独的类中,并让这个类包装它所需要装饰的对象。因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了。
装饰功能的核心是:把类中的装饰功能从类中搬出去。