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

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

设计模式-Decorator装饰模式_设计模式_02设计模式-Decorator装饰模式_设计模式_03
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类,同时又是具体装饰类的基类,此处它代表“装饰”概念,但还没有进一步实例化为具体的“装饰”内容,代码如下:

设计模式-Decorator装饰模式_设计模式_02设计模式-Decorator装饰模式_设计模式_03
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全球定位功能,它们的代码如下:

设计模式-Decorator装饰模式_设计模式_02设计模式-Decorator装饰模式_设计模式_03
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();
        }
    }
}

 

设计模式-Decorator装饰模式_设计模式_02设计模式-Decorator装饰模式_设计模式_03
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,当然你还可以定义其它的被装饰对象如宝马车,奔驰车.........代码如下:

设计模式-Decorator装饰模式_设计模式_02设计模式-Decorator装饰模式_设计模式_03
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();
        }
    }
}

应用程序代码:

设计模式-Decorator装饰模式_设计模式_02设计模式-Decorator装饰模式_设计模式_03
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装饰模式_设计模式_14


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

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

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

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

前往:设计模式学习笔记清单