天天看点

连载:面向对象葵花宝典:思想、技巧与实践(40) - DECORATOR模式

掌握了设计模式之道后,我们将以全新的方法来理解设计模式,这个方法更简单、更直观,不信?看几个样例就知道了

=====================================================================

decorator模式(以设计模式之道来理解)

【业务】

假设你进入了一个信息安全管理非常严格的公司,这家公司不允许员工自行打印文档,所有的文档打印都需要交给文档打印系统统一管理。文档打印系统会记录每次打印的时间、内容、打印人员。。。。。。等等,以便后续出现问题的时候进行追查。

由于公司有很多的部门,每个部门的安全要求并不完全一样,同时每个部门关于文档打印也有自己的一些规定。

我们的任务就是要开发一套能够支持整个公司文档打印需求的系统。

【发现变化】

文档打印系统面对的变化主要体现在:文档打印要求是变化的,不同的部门有不同的要求,同一个部门也可能修改自己的打印需求。

例如:

a部门是一个战略规划的部门,里面的资料都非常重要,打印的时候需要在页眉位置打印“绝密”,在页脚的位置打印“密级申明”,同时要加上“绝密文档”的水印;

b部门是内部培训部门,打印培训材料的时候需要在页眉位置打印“内部公开”,但不需要密级申明,同时加上“培训资料”的水印

c部门是对外宣传部门,打印宣传材料的时候只需要加上“公司logo”的水印;

【传统方法】

传统方法使用类继承来封装打印请求,为每个部门创建一个打印的子类。详细示例代码如下:

printtask.java -- 文档打印系统开发小组负责维护

secretprint.java -- 文档打印系统开发小组负责维护:

internalprint.java -- 文档打印系统开发小组负责维护:

publicprint.java -- 文档打印系统开发小组负责维护:

文档打印系统实现如下:

printserver -- 文档打印系统开发小组负责维护

定义好不同的打印任务后,每个部门根据自己的需要,选择不同的任务发给文档打印系统。

例如,a部门的打印处理如下:

secretdepartment.java  -- a部门负责维护

传统方法使用类继承来封装变化的打印需求,当面对变化时,存在如下问题:

1)新增部门的时候,需要文档打印系统提供一个新的打印任务类,将导致出现大量的***print类;

例如:新建了一个d部门,d部门只需要打印纯文本即可,那么已有的secretprint、internalprint、publicprint类都无法满足需求,必须新增一个pureprint的类;

2)某个部门的打印需求变更的时候,需要改变已有的***print类;

例如:c部门希望在对外宣传材料的页眉上打印公司名称,则需要修改publicprint类。

【设计模式方法】

设计模式封装变化的方法就是decorator模式。decorator模式定义如下:

“动态的给一个对象添加一些额外的职责”

《设计模式》一书中关于decorator模式的描述并不很直观,我理解decorator模式为“通过聚合的方式将动态变化的职责组合起来”。

我们详细看看decorator模式是如何封装变化的。

首先,将变化的职责封装为独立的类。传统方式实现中,不同的职责是对应不同的函数调用,而设计模式中,不同的职责是不同的类;

其次,通过聚合将变化的职责组合起来。传统方式中,不同职责的组合是通过在一个函数中写多行代码来体现的,而设计模式中,通过对象的聚合将不同职责组合起来。

【decorator模式结构】

连载:面向对象葵花宝典:思想、技巧与实践(40) - DECORATOR模式

component:定义一个对象接口(对应结构图中的operation函数),可以给这些对象动态添加职责

concretecomponent:定义一个对象,这个对象是实际的component,将被decorator修饰

decorator:定义修饰对象的接口,decorator实现的关键在于聚合了一个component对象

concretedecorator:具体的修饰对象

【代码实现】

使用decorator设计模式实现的文档打印系统代码如下:

*********************类设计*****************************

printcomponent.java -- 文档打印系统开发小组负责维护

printdecorator.java -- 文档打印系统开发小组负责维护

textcomponent.java -- 文档打印系统开发小组负责维护

headerdecorator.java -- 文档打印系统开发小组负责维护

footerdecorator.java

textwatermarkdecorator.java

imgwatermarkdecorator.java

printserver.java 

*********************类使用*****************************

a部门的打印处理如下(如下代码请仔细阅读,特别是注释部分):

可以看到,使用了设计模式的方法后,打印业务的变化,可以通过类似数学上的排列组合已有的打印功能来完成,而不再需要新的打印类了。

================================================ 

转载请注明出处:http://blog.csdn.net/yunhua_lee/article/details/38865605

继续阅读