装饰模式:Decorator(转自LoveCherry)
意图<?XML:NAMESPACE PREFIX = O />
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
场景
在设计网络游戏的武器系统时,开始并没有考虑到武器的强化和磨损。之后,策划人员说希望给游戏增加强化系统和修理系统,那么我们的武器类型就需要对外提供强化、磨损、修理等方法了。发生这种改动是我们最不愿意看到的,按照设计原则,我们希望功能的扩展尽可能不要修改原来的程序。你可能会想到使用继承来实现,但是策划人员的需求是有的武器能磨损能修理,不能强化,有的武器能强化,但是不会磨损,有的武器既能强化还能磨损和修理。遇到这样的情况,继承的方案可能不适合了,一来继承的层次可能会很多,二来子类的数量可能会很多。
由此,引入装饰模式来解决这个问题。装饰模式使得我们能灵活赋予类额外的职责,并且使得设计和继承相比更合理。
示例代码
using System; using System.Collections.Generic; using System.Text; namespace DecoratorExample { class Program { static void Main(string[] args) { Weapon w = new Rifle(); w.ShowInfo(); Enhance enhancedWeapon = new Enhance(w); enhancedWeapon.EnhanceAmmo(); enhancedWeapon.ShowInfo(); Wear wornWeapon = new Wear(w); wornWeapon.WearByRate(0.8); wornWeapon.ShowInfo(); } } abstract class Weapon { private double ammo; public double Ammo { get { return ammo; } set { ammo = value; } } private double attack; public double Attack { get { return attack; } set { attack = value; } } private double speed; public double Speed { get { return speed; } set { speed = value; } } private string name; public string Name { get { return name; } set { name = value; } } public abstract void ShowInfo(); } class Rifle : Weapon { public Rifle() { this.Ammo = 100; this.Attack = 10; this.Speed = 5; this.Name = "Rifle"; } public override void ShowInfo() { Console.WriteLine(string.Format("ammo\t{0}", Ammo)); Console.WriteLine(string.Format("attack\t{0}", Attack)); Console.WriteLine(string.Format("speed\t{0}", Speed)); Console.WriteLine(string.Format("name\t{0}", Name)); } } abstract class Decorator : Weapon { protected Weapon w; public Decorator(Weapon w) { this.w = w; } public override void ShowInfo() { w.ShowInfo(); } } class Enhance : Decorator { public Enhance(Weapon w) : base(w) { } public void EnhanceAmmo() { w.Ammo += 20; Console.WriteLine(">>>>>>>>>>>>Enhanced"); } } class Wear : Decorator { public Wear(Weapon w) : base(w) { } public void WearByRate(double rate) { w.Speed = w.Speed * rate; w.Attack = w.Attack * rate; Console.WriteLine(">>>>>>>>>>>>Worn"); } } } |
代码执行结果如下图:
代码说明
l Weapon是抽象构件角色。
l Rifle是具体构件角色,实现抽象构件的接口。
l Decorator是装饰角色。装饰角色有两个特点,一是继承了抽象构件的接口,二是有一个构件角色的实例。
l Enhance和Wear是具体装饰角色,它们负责给构件附加责任。
l 客户端在使用装饰角色的时候并没有针对抽象构件进行编程,因为我们确实需要使用具体装饰角色提供的额外方法,这种类型的装饰叫做半透明装饰。
何时采用
l 从代码角度来说,如果你觉得由于功能的交叉扩展不会导致非常多的子类或者非常多的继承层次的话可以考虑装饰模式。
l 从应用角度来说,如果你希望动态给类赋予或撤销一些职责,并且可以任意排列组合这些职责的话可以使用装饰模式。
实现要点
l 让装饰角色还继承抽象构件角色也是装饰模式最大的特点,目的就是给抽象构件增加职责,对外表现为装饰后的构件。
l 让装饰角色拥有构件角色实例的目的就是让构件能被多个装饰对象来装饰。
l 在具体应用中可以灵活一点,不一定要有抽象构件和装饰角色。但是,装饰对象继承装饰对象并且拥有它实例的两大特点需要体现。
l 透明装饰一般通过在基类方法前后进行扩充实现,半透明装饰一般通过新的接口实现。
注意事项
l 装饰模式和桥接模式的区别是,前者是针对功能的扩展,本质上还是一样东西,而后者针对多维护变化。装饰模式的思想在于扩展接口而桥接模式的思想是分离接口。
l 装饰类可能会比较琐碎,并且不利于复用,装饰模式在增加了灵活性的同时也降低了封装度,在实际应用中可以和其它模式配合。
转载于:https://www.cnblogs.com/guojingyang/archive/2008/12/03/1346659.html
装饰模式:Decorator(转自LoveCherry)相关推荐
- 装饰模式(Decorator)简介
装饰模式是第三个介绍的模式了. 这个模式没有前面两个那么好理解., 一, 装饰模式(decorator)的定义. 教材里是这样写的: 动态第给1个对象添加1写额外的职责(功能), 就增加的功能来讲, ...
- 二十四种设计模式:装饰模式(Decorator Pattern)
装饰模式(Decorator Pattern) 介绍 动态地给一个对象添加一些额外的职责.就扩展功能而言,它比生成子类方式更为灵活. 示例 有一个Message实体类,某个对象对它的操作有Insert ...
- 设计模式(13):结构型-装饰模式(Decorator)
设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...
- 七、装饰模式(Decorator Pattern)
一.介绍 意图:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰器模式相比生成子类更为灵活. 主要解决:使用继承实现类的功能的扩展,有时子类会过多的问题. 应用实例: 1.一幅照片,将它放入玻 ...
- 装饰模式Decorator
装饰模式Decorator /*** 抽象构件角色* @author InJava ...
- 装饰模式(Decorator)
1.概念 装饰模式动态地给一个对象添加一些额外的职责.就扩展功能而言,它比生成子类方式更为灵活,属于结构性模式一种. 2.模式结构 抽象组件角色(Component):定义一个对象接口,以规范准备接受 ...
- 设计模式之装饰模式(Decorator)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- c语言装饰,C++设计模式之装饰模式(Decorator)
装饰模式是一种经典的类功能扩展模式,其精髓在装饰类使用继承加聚合的方式获得接口和要实现对象,然后通过自己实现扩展接口 作用装饰模式通过装饰类动态地将责任附加到对象上,若要扩展功能,无需通过继承增加子类 ...
- 《研磨设计模式》chap22 装饰模式Decorator(4)AOP+总结
1. AOP面向方面编程 共性功能 AOP调用示意图 public class SaleModel { private String goods; //销售的商品 public String getG ...
- 《研磨设计模式》chap22 装饰模式Decorator(1)模式简介
场景:算员工奖金,各种奖金,有个人销售奖,团队奖,环比增加销售奖等等 1. 正常编码 public class Prize {//计算某人在某段时间内的奖金,有些参数在演示中并不会使用, public ...
最新文章
- 生成allure测试报告时报错的解决方法
- 算法训练 素因子去重
- 67. Add Binary
- java string转number_Java运算符知识点总结
- LUA string的状态
- 下划线hover下动态出现技巧
- 【简便代码】1063 计算谱半径 (20分)_10行代码AC
- Chrome 74 稳定版发布,Windows 10 支持黑暗模式
- 用正则实现多行文本合并,从而保存为csv文件
- 前端学习(2037)vue之电商管理系统电商系统之优化
- 45.UITableView去除分割线
- oracle:中位数查询整理
- 秋招复习-后端(C++)
- win7键盘失灵 登陆界面键盘失效无法输入密码的解决办法
- c#使用 Newtonsoft.Json 将entity转json时,忽略为null的属性
- 层次分析法、模糊综合评测法实例分析(涵盖各个过程讲解、原创实例示范、MATLAB源码公布)
- 课程设计---宾馆客房管理系统
- 安卓android usb 转 RS 232 串口 芯片的比较
- matlab 多变量最小值,【求助】用fmincon求含有多组变量的目标函数的最小值问题...
- 转自--暗夜子羽--文章
热门文章
- 基于HTML5的iPad电子杂志横竖屏自适应方案
- Android提升篇系列:Activity recreate(Activity 重新创建/自我恢复)机制(一)
- Phoenix官方教程 (一) 构建和运行
- tomcat运行模式(bio,aio,apr)
- HttpClient4.3.x的连接管理
- 按照鬼哥学so变化,四,第一章的例子
- mongodbVUE基本操作(转)
- 路由器-配置(思科)
- leaflet自定标签json_Windows Terminal更新后,自定义配置失效?快捷键无法使用?
- record.php play.php,record.php