装饰模式(Decorator)简介
装饰模式是第三个介绍的模式了.
这个模式没有前面两个那么好理解.,
一, 装饰模式(decorator)的定义.
教材里是这样写的:
动态第给1个对象添加1写额外的职责(功能), 就增加的功能来讲, 装饰模式比生成子类更加灵活.
就咁睇的确很难明白. 但我们起码可以知道一下两点:
1. 装饰模式的作用是增强1个对象(类) 的功能.
2. 它比生成子类更加灵活.
本文着重讲下第2点, 包括什么是生成子类, 为什么装饰模式比它更加灵活.
二, 1个Hunter1(猎人)类的例子.
举1个很简单的例子. 1个猎人类实现1个打猎的接口.
Huntable 接口:
public interface Huntable {public void hunt();
}
猎人类Hunter1:
public class Hunter1 implements Huntable{public void eat(){System.out.println("eating!");}public void hunt(){System.out.println("Hunter is Hunting!");}
}
可见Hunter1这个类实现了Huntable借口.
hunt()方法里只简单重写了hunt()方法.
客户端代码:
Hunter1 h = new Hunter1();
h.hunt();
输出:
Hunter is Hunting!
1个增强hunt()方法的需求:
好了, 现在有1个猎人, 他出去不只是打猎, 他打猎的同时还同时训练它的猎狗, 最后还会给战利品拍一张照片.
也就是需要增强hunt()方法功能.
加上
trainDog() 和 takePic()这个两个方法.
怎么实现呢?
三, 通过添加子类Hunter2方法来增强Hunter1
open-closed principle:
可能有人会觉得. 直接在Hunter1里加上两个方法trainDog () 和 takePic(), 在hunt()里调用这个两个新方法不就完事了吗.
的确, 但是这种做法修改了原有的类, 违反了"封闭-开放原则".
所谓"封闭-开发原则" 就是对修改封闭, 对扩展开放.
在项目中, 很多旧的业务类根本不会让你修改(jar包发布或者你没有权限)
所以我们应该把这个新需求当做1个扩展来处理, 而不是修改旧代码.
其中1个方法就是增加子类.
新增1个Hunter2 类:
public class Hunter2 extends Hunter1{@Overridepublic void hunt(){super.hunt();this.trainDog();this.takePic();}//new function()public void trainDog(){System.out.println("Train the Dog!");}public void takePic(){System.out.println("Take a picture!");}
}
客户端代码:
Hunter2 h2 = new Hunter2();
h2.hunt();
UML:
可见, 这种方法, 只是新增了1个子类, 以及修改客户端代码, 对原来的类代码没有任何修改, 是符合"封闭-修改 原则"的.
这种修改, 增强了原来的类Hunter1 的hunt()功能, 可以说是"装饰"了原来的hunt()方法.
但是这种修改不是很灵活.
比如: 这种猎人是先打猎,再训狗,再拍照的.
如果有一种猎人喜欢先拍照再训狗了, 我们就又要增加1个Hunter1的子类了....
而装饰模式能解决问题.
四, 通过装饰模式来增强Hunter类.
Huntable 接口 和 Hunter类:
首先构造两个相同的接口和类:
public interface Huntable {public void hunt();
}
public class Hunter implements Huntable {public void eat(){System.out.println("eating!");}@Overridepublic void hunt(){System.out.println("Hunter is Hunting!");}
}
Hunter类跟上面的Hunter1类是完全一样的.
下面开始构造新的类来强化hunt()方法.
抽象装饰角色类 HuntOperation:
无论, 是训狗trainDog() 还是拍照takePic() 都是对hunt()的增强.
我们新增1个HuntOperation类, 让它继承Hunter类, 让它能重写hunt()方法.
public abstract class HuntOperation extends Hunter{private Hunter hunter = null;//setting componentpublic HuntOperation(Hunter hunter){this.hunter = hunter;}//actually execute component's hunt() method@Overridepublic void hunt(){if (null != hunter){hunter.hunt();}}
}
注意, 这个类有1个Hunter对象成员.
在hunt()方法里, 执行的实际上是成员Hunter对象的hunt()方法.
具体的装饰行为类 HuntTakePic():
照相类, 就让它继承抽象行为类 HuntOperation类.
public class HuntTakePic extends HuntOperation{public HuntTakePic(Hunter hunter) {super(hunter);}@Overridepublic void hunt(){super.hunt();this.takePic();}public void takePic(){System.out.println("Taking a Picture!");}
}
可见, 它先执行性成员Hunter对象的hunt()方法, 在执行自己的照相方法.
具体的装饰行为类 HuntTrainDog():
同样, 这个类也继承HuntOperation.
先执行Hunter对象的hunt()方法, 再执行自己的TrainDog方法.
public class HuntTrainDog extends HuntOperation{public HuntTrainDog(Hunter hunter) {super(hunter);// TODO Auto-generated constructor stub}@Overridepublic void hunt(){super.hunt();this.trainDog();}public void trainDog(){System.out.println("Training the dog!");}}
客户端代码:
客户端代码如下:
先构建1个Hunter对象h, 然后再基于h构建HuntTakePic htp, 然后在基于htp构建HuntTrainDog 对象htd.
最后执行htd的hunt()方法.
Hunter h = new Hunter();HuntTakePic htp = new HuntTakePic(h);HuntTrainDog htd = new HuntTrainDog(htp);htd.hunt();
实际上, 就先执行Hunter对象的hunt(), 再执行HuntTakePic对象的hunt(), 最后才执行HuntTrainDog对象的hunt()
输出:
Hunter is Hunting!
Taking a Picture!
Training the dog!
UML:
装饰模式的灵活性:
好了, 这种模式一样能增强Hunter类的hunt()
那么它到底比第一种方法灵活在哪里呢.
很简单, 假如另1类猎人想调换训狗, 和照相的顺序, 只需修改客户端的构建循序, 并需要再新增1个子类.
这就是装饰模式的灵活性.
有人会觉得, 装饰模式同样需要增加子类啊, 实际上, 假如我们为Hunter的hunt()再增加1个子行为, 例如给猎物剥皮.
那么只需要增加1个抽象行为HuntOperation的子类, 而不是Hunter的子类..
五, 小结
其实想深一层, 装饰模式之所以叫装饰模式.
是因为装饰不能改变原有的功能的行为.
就如上面的例子, Hunter里原来的hunt()方法没有改变, 只是增加了一些额外的功能.
所以如果需要从根本上改变Hunter里hunt()的代码, 装饰模式就不适用了, 还是建议用增加Hunter子类的方法.
装饰模式(Decorator)简介相关推荐
- 二十四种设计模式:装饰模式(Decorator Pattern)
装饰模式(Decorator Pattern) 介绍 动态地给一个对象添加一些额外的职责.就扩展功能而言,它比生成子类方式更为灵活. 示例 有一个Message实体类,某个对象对它的操作有Insert ...
- 设计模式(13):结构型-装饰模式(Decorator)
设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于 ...
- 七、装饰模式(Decorator Pattern)
一.介绍 意图:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰器模式相比生成子类更为灵活. 主要解决:使用继承实现类的功能的扩展,有时子类会过多的问题. 应用实例: 1.一幅照片,将它放入玻 ...
- 装饰模式Decorator
装饰模式Decorator /*** 抽象构件角色* @author InJava ...
- 《研磨设计模式》chap22 装饰模式Decorator(1)模式简介
场景:算员工奖金,各种奖金,有个人销售奖,团队奖,环比增加销售奖等等 1. 正常编码 public class Prize {//计算某人在某段时间内的奖金,有些参数在演示中并不会使用, public ...
- 装饰模式(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 ...
最新文章
- iframe父子页面交互
- Python Numba实现GPU加速
- QT入门安装篇+helloworld(辛酸血泪)
- Ironport对邮件主题中包括特殊字符的过滤
- SAP CRM和C4C的订单Number range
- 在 LinearLayout里addView一个图表
- 详解RPC远程调用和消息队列MQ的区别
- i2c通信 msp430g2553_msp430g2553的IIC通信
- Global Average Pooling对全连接层的可替代性分析(转)
- 利用gsm模块自动收发短信
- spring使用之旅(二) ---- AOP的使用
- Python输出函数print()总结(python print())
- 微信windows版本体验报告
- 【CAN】 PCAN Explorer5 常用操作使用简介
- 达人评测 小米笔记本pro14和联想yoga14s 选哪个好
- Linux性能优化实战学习笔记:第四十六讲=====实战分析
- websocket+cdn架构部署
- 使用Tensorflow训练LSTM+Attention中文标题党分类
- 令我“细思极恐”的Faster-R-CNN
- Python实现将位图描摹为彩色矢量 svg 图片的源代码,Python实现位图转彩色矢量代码