zoukankan      html  css  js  c++  java
  • 设计模式Decorator装饰模式

    Decorator装饰模式:主要用于动态地给一个对象添加一些额外的职责。就扩展功能而言,它比生成子类方式更为灵活。
    先进入我们的例子:
     程序如下图

                            
    定义抽象基类 AbsCar
    ,此处它代表一个抽象的“车”,它既是装饰类的基类,也是被装饰类的基类,其代码如下


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace DecoratorCar
    {
        
    abstract  class AbsCar
        {
     
            
    public virtual  void AddAccessary()
            {
                Console.WriteLine(
    "本车具备标准配置");
            }
        }
    }

    定义Decorator类,此类继承自AbsCar类,同时又是具体装饰类的基类,此处它代表“装饰”概念,但还没有进一步实例化为具体的“装饰”内容,代码如下:


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace DecoratorCar
    {
        
    class Decorator:AbsCar  //继承接口(IS A AbsCar)
        {
            
    private AbsCar _car;  //也合成AbsCar (HAS A AbsCar)

            
    public Decorator(AbsCar car)
            {
                
    this._car = car;
            }
            
    public override void  AddAccessary()
            {
                _car.AddAccessary();
            }
         }
    }

    定义具体的装饰类DecoratorCruiseCtrl,DecoratorGPSCtrl两个类,它们继承自Decorator类,代表具体的“装饰”内容,此处就是Cruise巡航功能和GPS全球定位功能,它们的代码如下:


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace DecoratorCar
    {
        
    class DecoratorCruiseCtrl:Decorator 
        {
            
            
    private string _cruise;
            
    public string Cruise
            {
                
    get { return _cruise; }
                
    set { _cruise = value; }

            }
            
    public DecoratorCruiseCtrl(AbsCar car)
                : 
    base(car)
            {  }

            
    public override void AddAccessary()
            {
                 
    //功能扩展
                this.Cruise = "添加Cruise控制系统";
                Console.WriteLine(
    this.Cruise);
                
    base.AddAccessary();
            }
        }
    }

     


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace DecoratorCar
    {
        
    class DecoratorGPSCtrl:Decorator
        {
            
    private string _gps;
            
    public string GPS
            {
                
    get { return _gps; }
                
    set { _gps = value; }

            }
            
    public DecoratorGPSCtrl(AbsCar car)
                : 
    base(car)
            {   }
            
            
    public override void AddAccessary()
            {
                
    //功能扩展
                this.GPS = "添加GPS控制系统";
                Console.WriteLine(
    this.GPS);
                
    base.AddAccessary();
            }
        }
    }

    定义具体的被装饰对象"丰田车":ToyotaCar,当然你还可以定义其它的被装饰对象如宝马车,奔驰车.........代码如下:


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace DecoratorCar
    {
        
    class ToyotaCar:AbsCar 
        {
            
    public ToyotaCar()
            {

            }
            
    public override void AddAccessary()
            {
                Console.WriteLine(
    "----------------------------");
                Console.WriteLine(
    "以上是给丰田车添加的其它功能");
                
    base.AddAccessary();
            }
        }
    }

    应用程序代码:


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace DecoratorCar
    {
        
    class Program
        {
            
    static void Main(string[] args)
            {
                ToyotaCar tcar 
    = new ToyotaCar();
                DecoratorCruiseCtrl dr 
    = new DecoratorCruiseCtrl(tcar);
                DecoratorGPSCtrl dc 
    = new DecoratorGPSCtrl(dr);
                dc.AddAccessary();       

                Console.ReadLine();

            }
        }
    }

    示例说明:
        由上面的程式可以了解,未來要添加一个新的功能,例如:想加一个天窗SunRoof,只要寫一個和DecoratorCruiseCtrl以及 DecoratorGPSCtrl功能一樣的class繼承Decorator。这个個模式最有趣的是,Decorator既繼承了AbsCar,也合成 AbsCar, 也就是说 Decorator 是装饰者模式里非常特殊的一个类,它既继承于 AbsCar【IS A关系】,又维护一个指向 AbsCar实例的引用【HAS A关系】,换个角度来说,Decorator 跟 AbsCar之间,既有动态组合关系,又有静态继承关系。
    1、为什么要这样设计?我们知道,组合的好处是可以在运行时给对象增加职责,Decorator【HAS A】AbsCar的目的,是让 Decorator可以在运行时动态地给 AbsCar增加职责,这一点相对来说还比较好理解;
    2、Decorator继承于 AbsCar的目的是什么?目的只有一个,那就是统一「装饰者」(DecoratorCruiseCtrl,DecoratorGPSCtrl或者其它任 何想加的具体Decorator)和「被装饰者」(丰田车或者其它任何品牌的车)的接口。换个角度来说,不管是什么被装饰者(丰田车)还是「装饰 者」(DecoratorCruiseCtrl,DecoratorGPSCtrl),它们都继承自最顶层的 AbsCar 基类,用户代码可以把它们统一看作 AbsCar来处理,这样带来的更深一层好处就是,「装饰者」对象(DecoratorCruiseCtrl,DecoratorGPSCtrl),对 「被装饰者」对象(丰田车)的功能职责扩展,对用户代码来说是完全透明的,因为用户代码引用的都是 AbsCar,所以就不会因为「被装饰者」(丰田车)对象在被装饰后,引用它的用户代码发生错误,实际上不会有任何影响,因为装饰前后,用户代码引用的都 是 AbsCar 类型的对象。
      因此「装饰模式」通过继承,实现统一了「装饰者」和「被装饰者」的接口,通过组合获得了在运行时动态扩展「被装饰者」对象的能力。
    程序运行效果:




    总结:
    Decorator Pattern 适用的情景:
    你拥有一个已存在的组件类,却无法继承它 (subclassing)。
    能够动态地为对象添加职责 (添加状态和行为)。
    改变类中的成员和行为,但不影响其他对象。
    希望能便于职责的撤消。
    不想用「继承」来扩展行为。其中一种原因是避免当一些功能要交叉搭配引用时,单独用「继承」来设计会产生太多的子类、太复杂的类图结构,另一种考量可能是因为类的定义被隐藏,或类的定义不能用于生成子类。

    Decorator Pattern 的优点:
    可避免单独使用「继承」时,在扩展时不够弹性,且可能衍生过多的子类。
    扩展时不需要修改既有的代码。
    可在执行时期,动态地添加新行为 (职责)。

    Decorator Pattern 的缺点:
    可能会在程序中出现许多的小型类,亦即需要编写很多 ConcreteDecorator 类 (具体装饰者)。
    若过度使用 Decorator 模式,会让程序逻辑变得很复杂。
    别人较不易理解设计方式及代码,排查故障、追踪和调试也比较困难。

    Decorator Pattern 的其他特性:
    每个要装饰的功能,都放在单独的类中。
    我们可以用无数个装饰者,去包装一个组件。
    「装饰者」可以在「被装饰者」前面或后面,添加自己的行为,甚至将「被装饰者」的行为整个取代掉,以达到特定的目的。
    「被装饰者」并不需要知道它已经被「装饰」过了,亦即 Component 类 (对象) 并不需要知道 Decorator 类 (对象) 的存在,且 Decorator 也仅仅认识 Component。

    前往:设计模式学习笔记清单
  • 相关阅读:
    笛卡尔树学习笔记
    图论基础(自认为很全)
    我的博客在这里
    C++学习资料
    test
    个人介绍
    CF1153F Serval and Bonus Problem
    【ZJOI2020】抽卡
    【LOJ】小 Q 的序列
    我的个人博客:https://xyix.github.io
  • 原文地址:https://www.cnblogs.com/smallfa/p/1594568.html
Copyright © 2011-2022 走看看