设计模式-装饰模式(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) 不适用于所有情况

  装饰器模式并不总是适用于所有的场景。在一些情况下,可能存在更简单、更直接的解决方案。

  四、使用场景

  在电商系统中,商品的价格计算可能涉及多个促销规则,比如打折、满减、优惠券等。通过装饰器模式,可以动态地为商品添加不同的促销活动,而不影响商品的核心功能。

  五、总结

  装饰器模式通过使用组合而非继承来扩展对象的功能,解决了继承带来的类爆炸、单一继承、运行时不灵活和高耦合等问题。

  这样设计使得系统更加灵活、可扩展和易于维护。

posted @ 2024-01-07 17:12  欢乐豆123  阅读(21)  评论(0编辑  收藏  举报