概述
在软件系统中,有时候我们会使用继承来扩展对象的功能,但是由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?这就是本文要讲的decorator模式。
意图
动态地给一个对象添加一些额外的职责。就增加功能来说,decorator模式相比生成子类更为灵活。[gof 《设计模式》]
结构图
图1 decorator模式结构图
生活中的例子
装饰模式动态地给一个对象添加额外的职责。不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。
图2 使用有画框的画作为例子的装饰模式对象图
装饰模式解说
在软件开发中,经常会遇到动态地为一个对象而不是整个类增加一些功能的问题,还是以我惯用的记录日志的例子来说明吧(也许在decorator模式里面用这个例子不是特别合适)。现在要求我们开发的记录日志的组件,除了要支持数据库记录databaselog和文本文件记录textfilelog两种方式外,我们还需要在不同的应用环境中增加一些额外的功能,比如需要记录日志信息的错误严重级别,需要记录日志信息的优先级别,还有日志信息的扩展属性等功能。在这里,如果我们不去考虑设计模式,解决问题的方法其实很简单,可以通过继承机制去实现,日志类结构图如下:
图3
实现代码如下:
| public abstract class log { public abstract void write(string log); } public class databaselog : log { public override void write(string log) { //......记录到数据库中 } } public class textfilelog : log { public override void write(string log) { //......记录到文本文件中 } } |
| public interface ierror { void seterror(); } public interface ipriority { void setpriority(); } public class dberrorlog : databaselog, ierror { public override void write(string log) { base.write(log); } public void seterror() { //......功能扩展,实现了记录错误严重级别 } } public class dbprioritylog : databaselog, ipriority { public override void write(string log) { base.write(log); } public void setpriority() { //......功能扩展,实现了记录优先级别 } } public class tferrorlog : textfilelog, ierror { public override void write(string log) { base.write(log); } public void seterror() { //......功能扩展,实现了记录错误严重级别 } } public class tfprioritylog : textfilelog, ipriority { public override void write(string log) { base.write(log); } public void setpriority() { //......功能扩展,实现了记录优先级别 } } |
| public class dbeplog : databaselog, ierror, ipriority { public override void write(string log) { seterror(); setpriority(); base.write(log); } public void seterror() { //......功能扩展,实现了记录错误严重级别 } public void setpriority() { //......功能扩展,实现了记录优先级别 } } public class tfeplog : databaselog, ierror, ipriority { public override void write(string log) { seterror(); setpriority(); base.write(log); } public void seterror() { //......功能扩展,实现了记录错误严重级别 } public void setpriority() { //......功能扩展,实现了记录优先级别 } } |
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器