- 浏览: 341318 次
- 性别:
- 来自: 广州
文章分类
最新评论
装饰模式(Decorator)又名包装(Wrapper)模式,装饰模式以对客户端透明的方式扩展对象的功能,是继承的一个替代方案.
一:引言
孙悟空有七十二般变化,他的每一种变化都给他带来一种附加本领。他变成鱼时,就可以到水里游泳,他变成鸟时,就可以在天上飞行,而不管悟空怎么变化,在二郎神眼里,他永远是那只猢狲.
装饰模式以对客户透明的方式动态地给一人对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同,装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。
装饰模式使用原来被装饰的类的一个子类的实例,把客户端的调用委派到被装饰类,装饰模式的关键在于这种扩展是完全透明的。老孙变成的鱼相当于老孙的子类,这条鱼与外界互动要通过"委派"交给老孙本尊,由老孙本尊采取行动,尽管老孙把自己"装饰"成了鱼,在二郎神眼里,他仍然是那只猢狲。
二:装饰模式的结构
在装饰模式中的角色有:
(A)抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加功能的对象
(B)具体构件(Concrete Component)角色:定义一个将要接收附加责任的类
(C)装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口
(D)具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加功能
下面给出装饰模式的示意性源代码:
这就意味着Decorator1的对象持有一个对Decorator2对象的引用,后者则持有一个对Decorator3的引用,再后者持有一个对具体构件ConcreteComponent对象的引用,这种链式的引用关系使装饰模式看上去像是一个LinkedList.
回到齐天大圣的例子:Component的角色由孙悟空扮演,ConcreteComponent的角色属于大圣本尊,就是猢狲本人,大圣的七十二变扮演的便是Decorator角色,而ConcreteDecorator的角色便是花,鸟,鱼等七十二般变化。
四:在什么情况下使用装饰模式
(1)需要扩展一个类的功能,或给一个类增加附加责任
(2)需要动态地给一个对象增加功能,这些功能可以再动态地撤消
(3)需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实
再回到齐天大圣的例子:
首先有一个大圣本尊的实例:
齐天大圣c = new大圣本尊();
然后,你把大圣"装饰"成一个雀儿:
齐天大圣bird = new雀儿(c);
由于"大圣本尊"是ConcreteComponent类,因此可以调用默认的构造子创建实例,而"雀儿"是装饰类,要装饰的是"大圣本尊",也即一个"猢狲"实例,换言之,上面的java语句把"猢狲"变成了"雀儿"(把雀儿的功能加到了"猢狲"身上)。由于多态性原则,"雀儿"构造子可以接受任何"齐天大圣"的子类的实例,这也就意味着可以把任何大圣的化身装饰成"雀儿",比如:
齐天大圣c = new大圣本尊();
齐天大圣fish = new鱼儿(c);
齐天大圣bird = new雀儿(fish);
五:使用装饰模式的优点和缺点
(1)装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性,它允许系统动态地决定"贴上"一个需要的"装饰",或者除掉一个不需要的"装饰",继承关系则不同,继承关系是静态的,它在系统运行就决定了。
。 。 。 。
六:模式实现的讨论
大多数情况下,装饰模式的实现都比本节的定义中给出的示意性实现要简单,对模式进行简化时需要注意以下情况:
(1)一个装饰类的接口必须与被装饰类的接口相容:ConcreteDecorator类必须继承自一个共同的父类Component
(2)尽量保持Component作为一个"轻"类:这个类的责任是为各个ConcreteDecorator类提供共同的接口,因此它应当重在提供接口而不是存储数据。在示例中Component是一个java接口,而在实际工作中,它可以是一个抽象类或者是一个具体类,此时,就应当注意不要把太多的逻辑和状态放在Component类里。
(3)如果只有一个ConcreteComponent类而没有抽象的Component类(接口),那么Decorator类经常可以是ConcreteComponent的一个子类,这样的话ConcreteComponent就要扮演双重角色。
(4)如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类,甚至只有两个ConcreteDecorator类的情况下都可以这样做,但是如果ConcreteDecorator类的数目大于三的话,使用一个单独的Decorator类来区分抽象和具体的责任就是必要的了。
透明性要求:
最后指出一个重要问题,通常叫做针对抽象编程,装饰模式对客户端的透明性要求程序不要声明一个ConcreteDecorator类型的变量,而应当声明一个Component类型的变量。用孙悟空的例子来说,必须永远把孙悟空的所有变化都当成孙悟空来对待,而如果把他变成的雀儿当成雀儿,那就被老孙骗了!换言之,下面的做法是对的:
齐天大圣c = new大圣本尊();
而下面的做法是不对的:
大圣本尊c = new大圣本尊();,这就意味着在ConcreteDecorator里不可以有Component里所没有的方法,为什么呢?如果在ConcreteDecorator里面有一个新的方法newMethod(),那么,客户端怎么调用这个newMethod()呢?记住客户端只有Component接口,而这个接口里并没有newMethod()方法。
半透明的装饰模式
纯粹的装饰模式很难找到,装饰模式的用意是在不改变接口的前提下,增强所考虑的类的性能,在增强性能的时候,往往要建立新的公开的方法,即便是在孙大圣的系统里,也需要新的方法。比如齐天大圣类并没有飞行能力,而雀儿有,这就意味着雀儿应当有一个fly()方法,再比如,齐天大圣并没有你的游泳能力,而鱼儿有,这就意味着在鱼儿类里应当有一个新的swim()方法。这就导致了大多数的装饰模式的实现都是"半透明"的,换言之,允许装饰模式改变接口,增加新的方法,这意味着客户端可以声明ConcreteDecorator类型的变量,从而可以调用ConcreteDeconrator类中才有的方法:
齐天大圣c = new大圣本尊();
雀儿bird = new雀儿(c);
bird.fly();
但是,只要客户端不需要调用这些属于装饰的方法,而只调用属于Component的方法,那么装饰模式就仍然等同于透明的
七:装饰模式与其他模式的关系
(1)装饰模式与适配器模式的区别和联系
它们都有一个别名,即包装(Wrapper)模式,但是这两个模式是很不一样的。适配器模式的用意是要改变所考虑的对象的接口而不一定改变对象的性能,而装饰模式的用意是要保持接口,从而增强所考虑对象的性能
(2)装饰模式将一个东西的表皮换掉,而保持它的内心,策略模式恰好相反,它在保持接口不变的情况下,使得算法可以互换,装饰模式的实现要求Component类尽量地"轻",而策略模式要求抽象策略类尽量"重"。
(3)装饰模式与合成模式的关系
装饰模式常常用在合成模式的行为扩展上,使用继承关系扩展合成模式的行为很困难,如果仅仅对抽象构件(Component)类还是合成类(Composite)类或者树叶类(Leaf)类使用继承,会导致多态性被破坏
八:一个例子GrepReader---半透明的装饰模式的应用
功能描述:Grep是Unix操作系统中的命令,可以用来处理对流的搜索,由于Grep给出的结果仍然是流,因此可以作为过滤器在任何一条管道线中使用,比如命令Grep BMW file在文件file中搜索所有含有BMW字样的行,并显示出来.本例就用java的i/o包来实现一个简单的搜索器,叫做Grep,进行类似的搜索.
(1)宏观设计
首先把程序进行功能的划分,也即宏观设计。这里采用MVC模式:
(A)模型(Model):即GrepReader类,是一个对输入的文件流进行处理的构件,真正的搜索就发生在这里,这是一个处理char流的构件.
(B)视图(View):即GrepView类,是一个简单的数据输出工具,它只是把数据打印到屏幕上
(C)控制器(Control):即Grep类,是系统的控制中心.
(2)微观设计
即考虑每个类的大概的实现是怎么样的
(3)源码
//运行: java Grep C:\\AJAX.txt Ajax
//如果某行以Ajax开头,程序就会打印出这一行的文字.
//在eclipse里为main方法传参数:run-->run configulation->main选项里选择要运行的类,argument里的program argument里输入参数后apply->run
九:一个发票系统(跳过)
一:引言
孙悟空有七十二般变化,他的每一种变化都给他带来一种附加本领。他变成鱼时,就可以到水里游泳,他变成鸟时,就可以在天上飞行,而不管悟空怎么变化,在二郎神眼里,他永远是那只猢狲.
装饰模式以对客户透明的方式动态地给一人对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同,装饰模式可以在不使用创造更多子类的情况下,将对象的功能加以扩展。
装饰模式使用原来被装饰的类的一个子类的实例,把客户端的调用委派到被装饰类,装饰模式的关键在于这种扩展是完全透明的。老孙变成的鱼相当于老孙的子类,这条鱼与外界互动要通过"委派"交给老孙本尊,由老孙本尊采取行动,尽管老孙把自己"装饰"成了鱼,在二郎神眼里,他仍然是那只猢狲。
二:装饰模式的结构
在装饰模式中的角色有:
(A)抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加功能的对象
(B)具体构件(Concrete Component)角色:定义一个将要接收附加责任的类
(C)装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口
(D)具体装饰(Concrete Decorator)角色:负责给构件对象"贴上"附加功能
下面给出装饰模式的示意性源代码:
package cai.milenfan.basic.test; import java.util.Enumeration; //抽象构件角色 public interface Component { //某个商业方法 void sampleOperation(); }
package cai.milenfan.basic.test; /** *这是一个装饰类,应该注意几点: * (1)有一个私有的属性component,其数据类型是构件Component * (2)接口的实现方法也值得注意,每一个实现的方法都委派给父类,但并不是单纯的委派,而是有功能的增强 */ public class Decorator implements Component{ private Component cmponent; public Decorator(){} public Decorator(Component component){ this.cmponent = component; } public void sampleOperation(){ cmponent.sampleOperation(); } }
package cai.milenfan.basic.test; //具体装饰角色 public class ConcreateComponent implements Component{ public ConcreateComponent(){ //write your code here } public void sampleOperation() { //write your code here } }
package cai.milenfan.basic.test; //具体装饰类 public class ConcreteDecorator extends Decorator{ //商业方法 public void sampleOperation(){ super.sampleOperation(); } } 装饰模式的对象图如下: new Decorator1( new Decorator2( new Decorator3( new ConcreteComponent(); ) ) );
这就意味着Decorator1的对象持有一个对Decorator2对象的引用,后者则持有一个对Decorator3的引用,再后者持有一个对具体构件ConcreteComponent对象的引用,这种链式的引用关系使装饰模式看上去像是一个LinkedList.
回到齐天大圣的例子:Component的角色由孙悟空扮演,ConcreteComponent的角色属于大圣本尊,就是猢狲本人,大圣的七十二变扮演的便是Decorator角色,而ConcreteDecorator的角色便是花,鸟,鱼等七十二般变化。
四:在什么情况下使用装饰模式
(1)需要扩展一个类的功能,或给一个类增加附加责任
(2)需要动态地给一个对象增加功能,这些功能可以再动态地撤消
(3)需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实
再回到齐天大圣的例子:
首先有一个大圣本尊的实例:
齐天大圣c = new大圣本尊();
然后,你把大圣"装饰"成一个雀儿:
齐天大圣bird = new雀儿(c);
由于"大圣本尊"是ConcreteComponent类,因此可以调用默认的构造子创建实例,而"雀儿"是装饰类,要装饰的是"大圣本尊",也即一个"猢狲"实例,换言之,上面的java语句把"猢狲"变成了"雀儿"(把雀儿的功能加到了"猢狲"身上)。由于多态性原则,"雀儿"构造子可以接受任何"齐天大圣"的子类的实例,这也就意味着可以把任何大圣的化身装饰成"雀儿",比如:
齐天大圣c = new大圣本尊();
齐天大圣fish = new鱼儿(c);
齐天大圣bird = new雀儿(fish);
五:使用装饰模式的优点和缺点
(1)装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性,它允许系统动态地决定"贴上"一个需要的"装饰",或者除掉一个不需要的"装饰",继承关系则不同,继承关系是静态的,它在系统运行就决定了。
。 。 。 。
六:模式实现的讨论
大多数情况下,装饰模式的实现都比本节的定义中给出的示意性实现要简单,对模式进行简化时需要注意以下情况:
(1)一个装饰类的接口必须与被装饰类的接口相容:ConcreteDecorator类必须继承自一个共同的父类Component
(2)尽量保持Component作为一个"轻"类:这个类的责任是为各个ConcreteDecorator类提供共同的接口,因此它应当重在提供接口而不是存储数据。在示例中Component是一个java接口,而在实际工作中,它可以是一个抽象类或者是一个具体类,此时,就应当注意不要把太多的逻辑和状态放在Component类里。
(3)如果只有一个ConcreteComponent类而没有抽象的Component类(接口),那么Decorator类经常可以是ConcreteComponent的一个子类,这样的话ConcreteComponent就要扮演双重角色。
(4)如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类,甚至只有两个ConcreteDecorator类的情况下都可以这样做,但是如果ConcreteDecorator类的数目大于三的话,使用一个单独的Decorator类来区分抽象和具体的责任就是必要的了。
透明性要求:
最后指出一个重要问题,通常叫做针对抽象编程,装饰模式对客户端的透明性要求程序不要声明一个ConcreteDecorator类型的变量,而应当声明一个Component类型的变量。用孙悟空的例子来说,必须永远把孙悟空的所有变化都当成孙悟空来对待,而如果把他变成的雀儿当成雀儿,那就被老孙骗了!换言之,下面的做法是对的:
齐天大圣c = new大圣本尊();
而下面的做法是不对的:
大圣本尊c = new大圣本尊();,这就意味着在ConcreteDecorator里不可以有Component里所没有的方法,为什么呢?如果在ConcreteDecorator里面有一个新的方法newMethod(),那么,客户端怎么调用这个newMethod()呢?记住客户端只有Component接口,而这个接口里并没有newMethod()方法。
半透明的装饰模式
纯粹的装饰模式很难找到,装饰模式的用意是在不改变接口的前提下,增强所考虑的类的性能,在增强性能的时候,往往要建立新的公开的方法,即便是在孙大圣的系统里,也需要新的方法。比如齐天大圣类并没有飞行能力,而雀儿有,这就意味着雀儿应当有一个fly()方法,再比如,齐天大圣并没有你的游泳能力,而鱼儿有,这就意味着在鱼儿类里应当有一个新的swim()方法。这就导致了大多数的装饰模式的实现都是"半透明"的,换言之,允许装饰模式改变接口,增加新的方法,这意味着客户端可以声明ConcreteDecorator类型的变量,从而可以调用ConcreteDeconrator类中才有的方法:
齐天大圣c = new大圣本尊();
雀儿bird = new雀儿(c);
bird.fly();
但是,只要客户端不需要调用这些属于装饰的方法,而只调用属于Component的方法,那么装饰模式就仍然等同于透明的
七:装饰模式与其他模式的关系
(1)装饰模式与适配器模式的区别和联系
它们都有一个别名,即包装(Wrapper)模式,但是这两个模式是很不一样的。适配器模式的用意是要改变所考虑的对象的接口而不一定改变对象的性能,而装饰模式的用意是要保持接口,从而增强所考虑对象的性能
(2)装饰模式将一个东西的表皮换掉,而保持它的内心,策略模式恰好相反,它在保持接口不变的情况下,使得算法可以互换,装饰模式的实现要求Component类尽量地"轻",而策略模式要求抽象策略类尽量"重"。
(3)装饰模式与合成模式的关系
装饰模式常常用在合成模式的行为扩展上,使用继承关系扩展合成模式的行为很困难,如果仅仅对抽象构件(Component)类还是合成类(Composite)类或者树叶类(Leaf)类使用继承,会导致多态性被破坏
八:一个例子GrepReader---半透明的装饰模式的应用
功能描述:Grep是Unix操作系统中的命令,可以用来处理对流的搜索,由于Grep给出的结果仍然是流,因此可以作为过滤器在任何一条管道线中使用,比如命令Grep BMW file在文件file中搜索所有含有BMW字样的行,并显示出来.本例就用java的i/o包来实现一个简单的搜索器,叫做Grep,进行类似的搜索.
(1)宏观设计
首先把程序进行功能的划分,也即宏观设计。这里采用MVC模式:
(A)模型(Model):即GrepReader类,是一个对输入的文件流进行处理的构件,真正的搜索就发生在这里,这是一个处理char流的构件.
(B)视图(View):即GrepView类,是一个简单的数据输出工具,它只是把数据打印到屏幕上
(C)控制器(Control):即Grep类,是系统的控制中心.
(2)微观设计
即考虑每个类的大概的实现是怎么样的
(3)源码
package cai.milenfan.basic.test; import java.io.BufferedReader; import java.io.FileReader; import java.io.FilterReader; import java.io.IOException; import java.io.Reader; public class GrepReader extends FilterReader{ protected String substring; protected BufferedReader in; private int lineNumber; protected GrepReader(FileReader in,String substring) { super(in); this.in = new BufferedReader(in); this.substring = substring; lineNumber =0; } public final String readLine()throws IOException{ String line; do{ line = in.readLine(); lineNumber ; }while(line!=null&&line.indexOf(substring)==-1); return line; } public int getLineNo(){ return lineNumber; } }
package cai.milenfan.basic.test; import java.io.PrintStream; public class GrepView { PrintStream out; public GrepView(){ out = System.out; } public void println(String line){ out.println(line); } } package cai.milenfan.basic.test; import java.io.*; public class Grep { static GrepReader g; private static GrepView gv = new GrepView(); public static void main(String[] args){ String line; if(args.length<=1){ gv.println("Usage:java Grep "); gv.println(" no regexp"); gv.println(" files to be searched in"); System.exit(1); } gv.println("\nGrep:搜索" args[0] "文件" args[1]); gv.println("文件号和行号\r\t下面的行里含有所搜索的字符串\n"); try { g = new GrepReader(new FileReader(args[0]),args[1]); for(;;){ line = g.readLine(); if(line==null){ break; } gv.println(args[1] ":" g.getLineNo() ";\t" line); } g.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
//运行: java Grep C:\\AJAX.txt Ajax
//如果某行以Ajax开头,程序就会打印出这一行的文字.
//在eclipse里为main方法传参数:run-->run configulation->main选项里选择要运行的类,argument里的program argument里输入参数后apply->run
九:一个发票系统(跳过)
发表评论
-
Mina重连
2014-05-26 21:29 2927import com.sun.swing.internal. ... -
面试经典
2014-05-24 09:29 6431.mysql innodb引擎,什么叫聚集索引,与非聚集索 ... -
一拍网网站系统架构图
2014-03-28 21:24 623一拍网网站系统架构图 -
Window下安装配置nginx
2013-08-12 16:53 809安装:http://www.cnblogs.com/wen ... -
使用线程池的好处
2013-07-18 14:41 1252使用线程池有两个好处: 1.可以创建和销毁线程所带来的系统 ... -
Java ThreadLocal使用浅析
2013-07-18 14:36 483ThreadLocal通过在其内部保存变量的副本,并且各个副本 ... -
MyBatis学习之简单增删改查操作、MyBatis存储过程、MyBatis分页、MyBatis一对一、MyBatis一对多
2013-07-05 13:06 1177http://blog.csdn.net/zhangwei ... -
分享一位网友的架构杂谈
2013-05-20 23:16 913不容类型的网站,并发处理不一样,例如针对sns这种类型的网站 ... -
JSP页面静态化
2013-04-08 09:20 890http://www.java-zone.org/644.ht ... -
Java compile to C++
2013-03-19 14:53 507http://code.google.com/a/eclips ... -
几个TCP Socket的通信框架
2013-03-19 12:26 996http://www.oschina.net/p/simple ... -
宝贝鱼
2013-03-18 23:54 692http://code.google.com/p/cshbbr ... -
将Java程序注册成系统服务(NT服务)
2013-03-16 16:14 604http://blog.csdn.net/small____f ... -
Java内存回收机制
2013-03-13 15:47 814http://www.iteye.com/blogs/tag/ ... -
支付宝,百付宝集成
2013-03-13 14:01 975http://help.alipay.com/support/ ... -
SSH+EXTJS项目下载
2013-03-11 23:02 437http://download.csdn.net/tag/Ex ... -
Hibernate中使用Threadlocal创建线程安全的Session
2013-03-04 20:39 592http://blog.sina.com.cn/s/blog_ ... -
Java Socket多线程通信
2012-10-09 09:53 839当Server没接受到一个Client连接请求之后,都把处理流 ... -
Java 多线程的一个例子
2012-10-09 09:48 1024目录: 1 synchronized的 ... -
app引擎
2012-07-10 09:39 0http://sae.sina.com.cn/ htt ...
相关推荐
第八讲:装饰模式 第九讲:策略模式 第十讲:观察者模式 第十一讲:享元模式 第十二讲:代理模式 第十三讲:外观模式 第十四讲:组合模式 第十五讲:桥接模式 第十六讲:适配器模式 第十七讲:解释器模式 ...
(三)装饰模式:装饰模式在不改变对象原有接口的前提下,动态地给对象添加新的功能,提供了一种比继承更灵活的扩展对象的方式。它遵循“开闭原则”和“里氏代换原则”。 (四)代理模式:代理模式为其他对象提供一...
无水印、可复制版本 ...十三、责任链模式 十四、解释器模式 十五、迭代器模式 十六、备忘录模式 十七、中介者模式 十八、状态模式 十九、观察者模式 二十、策略模式 二十一、模板方法模式 二十二、访问者模式
01第一讲简单工厂模式 02第二讲工厂方法模式 03第三讲抽象工厂模式 04第四讲工厂模式在开发中的运用 05第五讲单例模式 06第六讲原型模式 07第七讲建造者模式 08第八讲装饰模式 09第九讲策略模式 10第十讲观察者模式 ...
误区三:过度使用设计模式。设计模式是为了提高代码可读性、可维护性和灵活性,但并非所有问题都需要设计模式来解决。滥用设计模式可能导致代码过于复杂,反而降低了可理解性。 误区四:设计模式是万能解药。每个...
- 第十六章:迭代器模式 - 第十七章:观察者模式 - 第十八章:命令模式 - **翻译团队**:本书的中文版由PHPChina成员翻译完成,各章节分别由不同的译者负责。 #### 五、设计模式案例分析 - **单例模式**:确保类...
#### 第十二章:装饰器模式—功能增强的无缝集成 装饰器模式是一种结构型设计模式,它允许在不改变对象结构的情况下动态地添加新的功能。通过将对象包装在装饰器中,可以在运行时为对象添加职责,而无需修改原始类...
(三)装饰模式 7 (四)代理模式 9 (五)工厂方法模式 11 (六)原型模式 13 (七)模板方法模式 15 迪米特法则 16 (八)外观模式 16 (九)建造者模式(生成器模式) 19 (十)观察者模式 23 (十一)抽象工厂...
13. **第十三章:现实世界中的模式:更好的生活模式** - 探讨了设计模式如何应用于现实生活中的问题。 - 分享了一些实用的设计模式案例研究。 14. **附录:剩余的模式** - 简要介绍了其他一些重要的设计模式。...
#### 十三、责任链模式(Chain of Responsibility) **定义:** 责任链模式是一种行为型设计模式,允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条...
#### 三、设计模式的描述方法 **描述设计模式的方法:** 设计模式的描述通常包括以下几个部分: 1. **模式名称**:简洁明了地概括模式的核心。 2. **问题**:描述该模式所解决的问题背景及情境。 3. **解决方案**:...
十九、装饰模式 装饰模式动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。装饰模式在.NET中常用于在不改变接口的前提下扩展对象的功能。 二十、代理模式 代理模式为其他对象提供...
三、装饰者模式 定义:给一个对象动态的增加了一些额外的功能,装饰者提供一种更加灵活的可选方案来扩展功能。 应用条件:需要在运行时动态地增加对象的功能 案例:咖啡机 / 煎饼果子 类图: * Component(组件...
**定义**: 装饰模式动态地给一个对象添加一些额外的职责。就增加功能而言,装饰模式相比生成子类更加灵活。 **优点**: - 动态扩展对象的功能; - 比继承更加灵活。 **应用场景**: - 在不影响其他对象的情况下,...
#### 十、装饰者模式(Decorator) **定义**:装饰者模式是一种结构型设计模式,其目的是动态地给一个对象添加一些额外的职责。 **应用场景**:在为MM准备生日礼物时,可以通过装饰者模式不断添加新的元素,如照片...
《PHP设计模式介绍》导言 《PHP设计模式介绍》第一章 编程惯用法 《PHP设计模式介绍》第二章 值对象模式 《PHP设计模式介绍》第...《PHP设计模式介绍》第十二章 装饰器模式 《PHP设计模式介绍》第十三章 适配器模式
三、建造者模式(Builder) 建造者模式将复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。在C#中,可以使用接口定义建造者,然后由具体的建造者类实现,以构建不同类型的复杂对象。 四、代理...
第四章《简单工厂模式》和第十三章《装饰模式》分别讲解了如何通过工厂模式简化对象创建,以及装饰模式如何动态地增加对象功能,而不会破坏其原有的结构。 行为型模式则关注对象间的交互与责任分配,如第十八章...
装饰模式允许向一个现有的对象添加新的行为或责任,而无需修改其结构。C#中可以通过继承和组合来实现装饰模式。 十、建造者模式 建造者模式将复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。...
十三、状态模式 状态模式允许对象在其内部状态改变时改变其行为,对象看起来似乎修改了它的类。 十四、策略模式 策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于...