设计模式-装饰模式(Decorator)
设计模式-装饰模式(Decorator)
概要
记忆关键字:附加职责
定义:动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
分析:装饰模式通过对原有的类进行功能扩展。依靠组合来实现类功能的扩展,并且支持多种嵌套。动态地给对象添加功能,避免通过子类扩展功能。
类型:结构型
装饰模式结构图如下:
一、能解决什么问题
装饰器模式解决了在不修改现有类的情况下,为对象添加额外功能的问题。它通过创建装饰器类来包裹原始对象,使得功能可以在运行时动态组合,避免了子类数量爆炸和继承的局限性。这使得系统更具灵活性和可扩展性。
二、涉及的角色
下面通过给汽车扩展飞行和自动驾驶功能的例子来说明
1. Component接口
最基本的功能接口
代码示例如下:
1 public interface Car { 2 3 /** 4 * 行为 5 */ 6 void run(); 7 }
2. ConcreteComponent类
ConcreteComponent类是被包装的实现类,代码示例如下:
1 public class BenzCar implements Car{ 2 @Override 3 public void run() { 4 System.out.println("奔驰开车了"); 5 } 6 } 7 8 public class BmwCar implements Car{ 9 @Override 10 public void run() { 11 System.out.println("宝马开车了"); 12 } 13 }
3. Decorator抽象类
所有的包装类,都继承自Decorator抽象类,而Decorator类又实现了Component接口,这么做是为了实现多层嵌套包装。
1 public class CarDecorator implements Car{ 2 protected Car decoratorCar; 3 4 public CarDecorator(Car decoratorCar) { 5 this.decoratorCar = decoratorCar; 6 } 7 8 @Override 9 public void run() { 10 decoratorCar.run(); 11 } 12 }
4. ConcreteDecorator类
具体的包装类,用于扩充被包装类的功能,代码示例如下:
1 public class FlyCarDecorator extends CarDecorator{ 2 public FlyCarDecorator(Car decoratorCar) { 3 super(decoratorCar); 4 } 5 6 @Override 7 public void run() { 8 super.run(); 9 fly(); 10 } 11 12 public void fly() { 13 System.out.println("开启飞行汽车模式"); 14 } 15 } 16 17 18 public class AutoCarDecorator extends CarDecorator { 19 public AutoCarDecorator(Car decoratorCar) { 20 super(decoratorCar); 21 } 22 23 @Override 24 public void run() { 25 super.run(); 26 autoRun(); 27 } 28 29 public void autoRun() { 30 System.out.println("开启自动驾驶"); 31 } 32 33 }
5. 客户端类
1 public class Client { 2 public static void main(String[] args) { 3 BenzCar benzCar = new BenzCar(); 4 benzCar.run(); 5 System.out.println("=============分割线=============="); 6 7 AutoCarDecorator benzAutoCarDecorator = new AutoCarDecorator(benzCar); 8 9 benzAutoCarDecorator.run(); 10 11 System.out.println("=============分割线=============="); 12 13 FlyCarDecorator benzFlyCarDecorator = new FlyCarDecorator(benzAutoCarDecorator); 14 benzFlyCarDecorator.run(); 15 } 16 } 17 18 //运行结果 19 奔驰开车了 20 =============分割线============== 21 奔驰开车了 22 开启自动驾驶 23 =============分割线============== 24 奔驰开车了 25 开启自动驾驶 26 开启飞行汽车模式
三、优缺点分析
1. 优点
1)灵活性和可扩展性
装饰器模式允许动态地、透明地向对象添加新的职责,而无需修改其代码。这提供了更大的灵活性和可扩展性,使得系统更容易维护和升级。
2)避免类爆炸
装饰器模式通过组合而不是继承的方式来实现功能的添加,避免了类爆炸问题。通过组合,可以创建各种不同的组合,而不需要为每个具体组合创建一个新的类。
3) 符合开闭原则
装饰器模式支持对现有代码的修改关闭,对扩展开放。可以在不修改现有代码的情况下引入新的装饰器类,从而增加新的功能。
4) 低耦合
装饰器与被装饰对象之间是松耦合的关系,装饰器可以独立变化,减少了维护的复杂性。
5) 易于理解和使用
装饰器模式不需要深入理解系统的内部工作原理,因此较易于理解和使用。它提供了一种直观的方式来为对象添加功能。
2. 缺点
1) 复杂性增加
使用装饰器模式会引入许多小对象,可能导致代码复杂性增加。尤其是当有多个装饰器叠加使用时,代码可读性和维护性可能降低。
2) 顺序敏感
装饰器的顺序很重要。如果装饰器的添加顺序不正确,可能会导致意外的结果。这增加了使用装饰器模式的复杂性。
说明:装饰模式的装饰顺序很重要,最理想的情况是保证装饰类之间彼此独立,这样它们就可以以任意的顺序进行组合了。
3) 不适用于所有情况
装饰器模式并不总是适用于所有的场景。在一些情况下,可能存在更简单、更直接的解决方案。
四、使用场景
在电商系统中,商品的价格计算可能涉及多个促销规则,比如打折、满减、优惠券等。通过装饰器模式,可以动态地为商品添加不同的促销活动,而不影响商品的核心功能。
五、总结
装饰器模式通过使用组合而非继承来扩展对象的功能,解决了继承带来的类爆炸、单一继承、运行时不灵活和高耦合等问题。
这样设计使得系统更加灵活、可扩展和易于维护。