模式导读:
给你一个没装修的房子,让你利用自己的艺术细菌去想象如何去让自己的房子更加漂亮,更加完美。这就需要我们慢慢去思考了...通过动态的给一个对象增加新的功能,使无需通过继承的方式增加子类既能够扩展对象功能,使用对象的关联关系代替继承关系,更加灵活,同时类型体系的快速膨胀。至于使用继承关系实现为什么膨胀,看下面这张图你就清楚了。
很明显,如果对象的功能开始复杂起来时,我们需要重新定义一个新的对象来实现,这就增加了更多地子类,所以膨胀了。
参考类图:
1.Component抽象构件角色:使真实对象和装饰对象有相同的接口,这样,客户端对象就能够以真实对象相同的方式同装饰对象交互。
2.ConcretComponent具体构件角色(真实对象):如io流中的FileInputStream,FileOutputStream。
3.Decorator装饰角色:持有一个抽象构件的引用,装饰对象接收所有的客户端的请求,并把这些请求转发给真实的对象,这样就能够在真实对象调用前后增加新的功能。
4.ConcretDecorator具体装饰角色:负责给构件对象增加新的责任。
代码实现:
1.抽象构件类
1 package com.etc; 2 //抽象构件角色 3 public interface AbstractCar { 4 void move(); 5 }
2.具体构件类
1 package com.etc; 2 //具体构件角色 3 public class Car implements AbstractCar{ 4 5 @Override 6 public void move() { 7 System.out.println("**正常由人操控陆地行驶!**"); 8 } 9 10 }
3.装饰者角色类
1 package com.etc; 2 //装饰角色,将传入的不同请求转发给真实对象 3 public class Decorator implements AbstractCar{ 4 private AbstractCar car; 5 //构造器,用于接收具体的装饰子对象 6 public Decorator(AbstractCar car) { 7 super(); 8 this.car = car; 9 } 10 @Override 11 public void move() { 12 car.move(); 13 } 14 15 }
4.特征类
1 //将共同的特征抽取出来 ->swim,fly,ai 2 public class Feature { 3 4 // 私有化构造器 5 private Feature() { 6 7 } 8 9 // 可以潜水 10 public static void swim() { 11 System.out.println("具备潜水功能"); 12 } 13 14 // 可以飞 15 public static void fly() { 16 System.out.println("具备飞行功能"); 17 } 18 19 // 可以人工智能 20 public static void ai() { 21 System.out.println("具备人工智能"); 22 } 23 }
5.具体装饰角色类
1 public class SwimCar extends Decorator { 2 3 public SwimCar(AbstractCar car) { 4 super(car); 5 } 6 7 // 重写父类的方法,给车增加swim()的功能 8 public void move() { 9 super.move(); 10 Feature.swim(); 11 } 12 }
1 public class SwimFlyCar extends Decorator { 2 3 public SwimFlyCar(AbstractCar car) { 4 super(car); 5 } 6 7 // 重写父类的方法,给车增加fly(),swim()的功能 8 public void move() { 9 super.move(); 10 Feature.fly(); 11 Feature.swim(); 12 } 13 }
1 //具体的装饰角色 2 public class FlyCar extends Decorator { 3 4 public FlyCar(AbstractCar car) { 5 super(car); 6 } 7 8 // 重写父类的方法,给车增加fly()的功能 9 public void move() { 10 super.move(); 11 Feature.fly(); 12 } 13 }
1 public class AICar extends Decorator { 2 3 public AICar(AbstractCar car) { 4 super(car); 5 } 6 7 // 重写父类的方法,给车增加AI()的功能 8 public void move() { 9 super.move(); 10 Feature.ai(); 11 } 12 }
6.客户端类
1 package com.etc; 2 //根据情景需要给车增加不同的功能 3 public class Client { 4 5 public static void main(String[] args) { 6 //让车增加可以飞的功能 7 Car car=new Car(); 8 FlyCar flyCar=new FlyCar(car); 9 flyCar.move(); 10 //让车增加可以潜水的功能 11 SwimCar swimCar=new SwimCar(car); 12 swimCar.move(); 13 //让车增加可以潜水,飞的功能 14 SwimFlyCar sfCar=new SwimFlyCar(car); 15 sfCar.move(); 16 } 17 18 }
效果截图:
装饰模式的优缺点:
优点:
装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:
多层装饰比较复杂。
适用场景:
1、扩展一个类的功能。
2、动态增加功能,动态撤销。