设计模式学习笔记--Decorator装饰模式

本文详细介绍了装饰模式的概念及其在软件设计中的应用。通过一个具体的例子——为汽车添加不同的装饰功能,展示了如何利用装饰模式动态地为对象添加职责。该模式不仅避免了通过继承扩展功能时的局限性,还提供了更加灵活和强大的扩展机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

ContractedBlock.gif ExpandedBlockStart.gif Code
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类,同时又是具体装饰类的基类,此处它代表“装饰”概念,但还没有进一步实例化为具体的“装饰”内容,代码如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
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全球定位功能,它们的代码如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
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();
        }
    }
}

 

ContractedBlock.gif ExpandedBlockStart.gif Code
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,当然你还可以定义其它的被装饰对象如宝马车,奔驰车.........代码如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
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();
        }
    }
}

应用程序代码:

ContractedBlock.gif ExpandedBlockStart.gif Code
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。

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

转载于:https://www.cnblogs.com/wsdj-ITtech/archive/2009/10/05/1578097.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值