Decorator装饰模式是一种结构型模式,它主要是解决:“过度地使用了继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀(多继承)。继承为类型引入的静态特质的意思是说以继承的方式使某一类型要获得功能是在编译时。所谓静态,是指在编译时;动态,是指在运行时。

GoF《设计模式》中说道:动态的给一个对象添加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。

下面来看看Decorator模式的结构:

<?XML:NAMESPACE PREFIX = V /><?XML:NAMESPACE PREFIX = O />

看这个结构好像不是很明白,下面我根据代码讲解一下这个结构。我想了一个场景:我们现在用的手机功能很多,我就用Decorator模式实现一下对某个手机的GSP和蓝牙功能扩展。

首先,我们需要一个手机的接口或者是抽象类,我这里就用抽象类来实现,代码如下:

public abstract class AbstractCellPhone

{

public abstract string CallNumber();

public abstract string SendMessage();

}

AbstractCellPhone也就是结构图中的Component,然后,我再来实现Nokia和Moto的手机类,这类要继承AbstractCellPhone,也就是图中ConcreteComponent类要继承Component,实现代码如下:

public class NokiaPhone : AbstractCellPhone

{

public override string CallNumber()

{

return "NokiaPhone call sombody";

}

public override string SendMessage()

{

return "NokiaPhone send a message to somebody";

}

}

public class MotoPhone : AbstractCellPhone

{

public override string CallNumber()

{

return "MotoPhone call sombody";

}

public override string SendMessage()

{

return "MotoPhone send a message to somebody";

}

}

接下来我需要一个Decorator接口或者抽象类,实现代码如下:

public abstract class Decorator:AbstractCellPhone

{

AbstractCellPhone _phone;

public Decorator(AbstractCellPhone phone)

{

_phone = phone;

}

public override string CallNumber()

{

return _phone.CallNumber();

}

public override string SendMessage()

{

return _phone.SendMessage();

}

}

正如结构图中,这个Decorator即继承了AbstractCellPhone,又包含了一个私有的AbstractCellPhone的对象。这样做的意义是:Decorator类又使用了另外一个Component类。我们可以使用一个或多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。在下来,我要实现GSP和蓝牙的功能扩展,它们要继承自Decorator,代码如下:

public class DecoratorGPS : Decorator

{

public DecoratorGPS(AbstractCellPhone phone)

: base(phone)

{ }

public override string CallNumber()

{

return base.CallNumber() + " with GPS";

}

public override string SendMessage()

{

return base.SendMessage() + " with GPS";

}

}

public class DecoratorBlueTooth : Decorator

{

public DecoratorBlueTooth(AbstractCellPhone phone)

: base(phone)

{ }

public override string CallNumber()

{

return base.CallNumber() + " with BlueTooth";

}

public override string SendMessage()

{

return base.SendMessage() + " with BlueTooth";

}

}

最后,用客户端程序验证一下:

static void <?XML:NAMESPACE PREFIX = ST1 />Main(string[] args)

{

AbstractCellPhone phone = new NokiaPhone();

Console.WriteLine(phone.CallNumber());

Console.WriteLine(phone.SendMessage());

DecoratorGPS gps = new DecoratorGPS(phone);     //add GSP

Console.WriteLine(gps.CallNumber());

Console.WriteLine(gps.SendMessage());

DecoratorBlueTooth bluetooth = new DecoratorBlueTooth(gps); //add GSP and bluetooth

Console.WriteLine(bluetooth.CallNumber());

Console.WriteLine(bluetooth.SendMessage());

Console.Read();

}

执行结果:

NokiaPhone call sombody

NokiaPhone send a message to somebody

NokiaPhone call sombody with GPS

NokiaPhone send a message to somebody with GPS

NokiaPhone call sombody with GPS with BlueTooth

NokiaPhone send a message to somebody with GPS with BlueTooth

从执行的结果不难看出扩展功能已被添加。最后再说说Decorator装饰模式的几点要点:

1、通过采用组合、而非继承的手法,Decorator模式实现了在运行时动态的扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。

2、Component类在Decorator模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Component类应该透明——换言之Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。

3、Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。我们可以使用一个或多个Decorator对象来“装饰”一个Component对象,且装饰后的对象仍然是一个Component对象。(在这里我想谈一下我的理解:当我们实例化一个Component对象后,要给这个对象扩展功能,这时我们把这个Component对象当作参数传给Decorator的子类的构造函数——也就是扩展方法的功能类。对于引用类型传参时,实际上只是传递对象的地址,这样,在功能扩展是,操作的应该是同一个对象)

4、Decorator模式并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。Decorator是在运行时对功能进行组合。

转载于:https://www.cnblogs.com/wayne-ivan/archive/2006/10/18/532298.html

设计模式学习笔记(十)——Decorator装饰模式相关推荐

  1. 设计模式学习笔记——装饰(Decorator)模式

    设计模式学习笔记--装饰(Decorator)模式 @(设计模式)[设计模式, 装饰模式, decorator] 设计模式学习笔记装饰Decorator模式 基本介绍 装饰案例 类图 实现代码 Dis ...

  2. 步步为营 .NET 设计模式学习笔记 十四、Decorator(装饰模式)

    概述 在软件系统中,有时候我们会使用继承来扩展对象的功能,但是由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性:并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多 ...

  3. 设计模式学习笔记十:单例模式(Singleton Pattern)

    1.概述    单例模式(Singleton Pattern)又称单件模式,单例模式保证一个类仅有一个实例,并提供一个访问的他的全局访问点.通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你 ...

  4. 步步为营 .NET 设计模式学习笔记 十九、Chain of Responsibility(职责链模式)

    概述 在软件构建过程中,一个请求可能被多个对象处理,但是每个请求在运行时只能有一个接受者,如果显示指定,将必不可少地带来请求发送者与接受者的紧耦合. 如何使请求的发送者不需要指定具体的接受者?让请求的 ...

  5. 设计模式学习笔记十五——Command模式

    动机:将一组行为抽象为对象,实现行为请求者和行为实现者之间的解耦,并且支持对行为进行记录.撤销.重做.事务等处理. 场景:考虑一系列文档操作:打开.复制.剪切.粘帖. 结构 代码实现 /**//*   ...

  6. java 设计模式学习笔记十 bridge桥模式

    bridge桥模式 将抽象和行为划分开来,各自独立但能动态结合 抽象的接口 /**  * 咖啡抽象类  *   * @time 下午09:14:27  * @author retacn yue  * ...

  7. java 设计模式学习笔记十四 template模版模式

    /**  * 模版  *   * @time 下午09:58:00  * @author retacn yue  * @Email zhenhuayue@sina.com  */ public abs ...

  8. 步步为营 .NET 设计模式学习笔记系列总结

    设计模式我从开篇到23种设计模式的讲解总共花了进两个月的时间,其间有很多读者给我提出了很好的建议,同时也指出了我的不足,对此我表示感谢,正是由于很多读者的支持我才能坚持的写到最后.在此表示我真诚的谢意 ...

  9. java设计模式学习笔记之装饰模式

    java设计模式学习笔记之装饰模式 尊重原创,转载请注明出处,原文地址: http://blog.csdn.net/qq137722697 这是一个使用策略模式和构建模式设计的网络请求框架,去看看吧& ...

  10. 设计模式学习笔记清单

    设计模式学习笔记清单 关于设计模式许多人已经耳熟能详,这段时间结合李建忠的教学视频以及大量网络资料,把这部分过了一遍,整理出学习笔记,而真正的深入学习和理解只能在具体的开发环境中日积月累.      ...

最新文章

  1. 15 个 JavaScript Web UI 库 (转)
  2. jpa mysql sql分页查询语句_JPA多条件复杂SQL动态分页查询功能
  3. P1101 单词方阵
  4. 解决安卓模拟器没有网络的问题,刚开的做RN的我遇见这个问题真很头疼,所以希望看到我这篇文章能够解决。
  5. 写一个函数,使给定的一个二维数组(3×3)转置,即行列互换
  6. 在chrome里查询修改html代码,我需要在网页中直接编辑CSS?打开Web代码检查器
  7. win8.1硬盘安装ubuntu14.04双系统
  8. 在eclipse-oxygen-sts中,关于快捷键[CTRL + SHIFT + O]失效的问题
  9. java成员方法tostring_Java 工具类-toString
  10. 嵌入式技术栈之I2S
  11. django基础知识总结
  12. java实现敏感词汇判断
  13. 详解机器学习/深度学习中的梯度消失/梯度爆炸的原因/解决方案
  14. 8021什么意思_无线网络标准IEEE802.11n是什么意思
  15. 如何用Word批量制作专属邀请函
  16. Unity-Live2d(模型与贴图建立联系,渲染,显示图片)
  17. 全球与中国网络性能监控工具市场现状及未来发展趋势
  18. 11.位运算符:什么是位运算符???位运算符共有哪七种???位运算符和逻辑运算符的区别是什么???
  19. Windows中安装GCC教程
  20. 段视频伪原创 手机如何去除视频md5

热门文章

  1. VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION
  2. Eclipse高版本无法兼容FatJar的问题解决
  3. 数据结构源码笔记(C语言):二路归并排序
  4. linux管理员工作目录,密码管理员 - FPM2
  5. automation服务器不能创建对象是什么意思_从运营商角度来考虑为什么NAT不能搭建服务器?...
  6. VSCode 自定义html5模板
  7. Shiro.ini文件概述
  8. Spring IOC示例代码
  9. C语言程序设计基础及应用实例---第一节 printf函数的使用
  10. 用matplotlib的imshow显示图像,设置colorbar的颜色范围