本文参考:《修炼Java开发技术:在架构中体验设计模式和算法之美 于广编著》。
装饰模式是指给一个类添加一些额外的职责,并且在添加这些额外的职责时不会控制该类的执行逻辑。
装饰模式能够在不必改变原类文件盒使用继承的情况下,动态扩展一个对象的功能。装饰模式是通过创建一个包装对象来实现,也就是用装饰来包裹真实的对象。
装饰模式的特点:
1、装饰对象和真实对象有相同的接口,这样客户端对象就能够以与真实对象相同的方式同装饰对象交互。
2、.装饰对象包含一个真实对象的索引(reference)。
3、装饰对象接受所有的来自客户端的请求。它把这些请求转发给真实的对象。
4、装饰对象可以在转发这些请求以前或者以后增加一些附加的功能。
装饰模式与类继承的主要区别如下:
1、装饰模式是一种动态行为,对已经存在的类进行随意组合,而类的继承是一种静态行为,一个类定义成什么样子,其对象便具有什么功能,无法动态的改变。
2、装饰模式扩展的是对象的功能,不需要增加类的数量。而类继承扩展是类的功能,在继承的关系中,如果我们想增加一个对象的功能,我们只能通过继承关系,在子类中增加方法。
3、装饰模式是在不改变原类文件和使用继承的情况下,动态的扩展一个对象的功能,它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
4、装饰模式把对客户端的调用委派给被装饰的类,装饰模式的关键在于这种扩展是完全透明的。
举例:
制作蛋糕,蛋糕种类有是奶酪蛋糕、巧克力蛋糕、插花的巧克力蛋糕、贺卡的冰激凌蛋糕等等,在这里我们只需要关注蛋糕,而贺卡、插花只不过是起到了装饰的作用。现在我们想要什么就能生成什么。
package decorator.demo; /** * 蛋糕基类 * */ public abstract class Cake { String remark = "蛋糕"; public String getRemark() { return remark; } public abstract String getImpression();//用来描述吃蛋糕的感觉。。。。 }
实现装饰器抽象类:
package decorator.demo; /** * 其他用来添加蛋糕的东西 * @author Nicholas * */ public abstract class OtherDecorator extends Cake{ Cake cake; /** * 引用一个Cake. * 让被装饰者进入装饰者之中。这里用的是构造方法注入。 * 这样就可以调用Cake实例的方法了。 * @param cake */ public OtherDecorator(Cake cake){ this.cake=cake; } /** * 让装饰器的子类都去实现getRemark方法。业务需要每个装饰器都要有描述。 */ public abstract String getRemark(); }
实现一个乳酪蛋糕:
package decorator.demo; /** * 乳酪蛋糕 */ public class CheeseCake extends Cake{ /** * 乳酪蛋糕的构造方法 */ public CheeseCake(){ super.remark="乳酪蛋糕";//修改乳酪蛋糕的描述。 } /** * 实现了Cake抽象类的getImpression * 吃乳酪蛋糕的感觉。。 */ public String getImpression() { return "香甜感受"; } }
巧克力蛋糕
package decorator.demo; /** * 巧克力蛋糕 */ public class ChocolateCake extends Cake{ public ChocolateCake(){ super.remark="巧克力蛋糕"; } public String getImpression() { return "丝一般的润滑"; } }
冰淇淋蛋糕
package decorator.demo; /** * 冰淇淋蛋糕 * */ public class IceCake extends Cake{ public IceCake(){ super.remark="冰淇淋蛋糕"; } public String getImpression() { return "冰爽无比"; } }
贺卡装饰:
package decorator.demo; public class CardDecorator extends OtherDecorator { public CardDecorator(Cake cake) { super(cake); super.remark = "贺卡"; } public String getImpression() { return cake.getImpression()+","+"吃起来口感不错啊!!"; } public String getRemark() { return cake.getRemark()+"+"+super.remark; } }
鲜花装饰
package decorator.demo; /** * 给蛋糕添加的花 */ public class FlowerDecorator extends OtherDecorator{ /** * 构造函数 * 传入一个cake实例,也就是前面所实现的Cake的子类,如奶酪蛋糕,巧克力蛋糕等等。 * @param cake */ public FlowerDecorator(Cake cake){ super(cake);//调用父类的构造方法,可以获取Cake的实例了。就可以调用Cake实例的方法. super.remark="一朵玫瑰花"; } /** * 实现了装饰器抽象类的getImpression方法。 */ public String getImpression() { //这是重点。我们通过构造方法传入的cake实例。对cake进行了装饰,增加了新的功能。 return cake.getImpression()+","+"看到一朵花真是happy"; } public String getRemark() { return cake.getRemark()+"+"+super.remark; } }
坚果装饰
package decorator.demo; /** * 给蛋糕添加的坚果 * */ public class NutsDecorator extends OtherDecorator{ public NutsDecorator(Cake cake){ super(cake); super.remark = "果仁"; } public String getImpression() { return cake.getImpression()+","+"吃起来口感不错啊!!"; } public String getRemark() { return cake.getRemark()+"+"+super.remark; } }
美女1喜欢:乳酪蛋糕+一朵玫瑰花+果仁
package decorator.demo; public class MyGirl { public static void main(String[] args){ Cake cheeseCake = new NutsDecorator(new FlowerDecorator(new CheeseCake())); System.out.println("remark "+cheeseCake.getRemark()); System.out.println("impression "+cheeseCake.getImpression()); } }
结果:
remark 乳酪蛋糕+一朵玫瑰花+果仁
impression 香甜感受,看到一朵花真是happy,吃起来口感不错啊!!
美女2喜欢用果仁,花包装巧克力蛋糕。
package decorator.demo; public class MyGirlB { public static void main(String[] args){ //用果仁,花包装巧克力蛋糕。 Cake nutsFlowerChocolateCake = new NutsDecorator(new FlowerDecorator(new ChocolateCake())); System.out.println("remark "+nutsFlowerChocolateCake.getRemark()); //吃蛋糕的感受已经发生了改变。 System.out.println("impression "+nutsFlowerChocolateCake.getImpression()); } }
结果:
remark 巧克力蛋糕+一朵玫瑰花+果仁
impression 丝一般的润滑,看到一朵花真是happy,吃起来口感不错啊!!
在Java中流接口和装饰模式的关系
InputStream就是输入流的抽象接口,而FilterInputStream就相当于装饰器。
举例说明:
对英文进行移动2位加密,a->c y->a z->b
方法一
package decorator.demo; import java.io.IOException; import java.io.OutputStream; public class EncryptOutputStream extends OutputStream { private OutputStream os = null; public EncryptOutputStream(OutputStream os) { this.os = os; } @Override public void write(int a) throws IOException { a += 2; if (a >= (97 + 26)) { a -= 26; } this.os.write(a); } }
方法二
package decorator.demo; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; public class EncryptOutputStream2 extends FilterOutputStream { public EncryptOutputStream2(OutputStream os) { super(os); } @Override public void write(int a) throws IOException { a += 2; if (a >= (97 + 26)) { a -= 26; } super.write(a); } }
测试:
package decorator.demo; import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.io.IOException; import org.junit.Test; public class TestDecorator { @Test public void test() throws IOException { DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(new EncryptOutputStream( new FileOutputStream("mytest.txt")))); dout.write("abcdxyz".getBytes()); dout.close(); } @Test public void test2() throws IOException{ DataOutputStream dout = new DataOutputStream(new EncryptOutputStream2 (new BufferedOutputStream( new FileOutputStream("mytest.txt")))); dout.write("abcdxyz".getBytes()); dout.close(); } }
test1和test2的区别在于BufferedOutputStream和EncryptOutputStream2可以在位置上互换,而EncryptOutputStream则不行,因为EncryptOutputStream2继承的是装饰器的父类,使用装饰器提供的功能协助完成想要装饰的功能。而EncryptOutputStream仅仅只是outputStream的子类。
方法二更合理。
相关推荐
### 开发模式之装饰模式详解 #### 装饰模式定义 装饰模式(Decorator Pattern)是一种结构型设计模式,允许向对象动态地添加新的功能,而无需修改其原有结构。这种模式通过创建一个新的包装类来包裹真实的对象,...
装饰模式是一种设计模式,它允许我们在不修改原有对象的基础上,通过添加新的行为或属性来扩展对象的功能。在"装饰模式小猪快跑游戏模拟"这个实例中,我们看到这种模式被巧妙地应用到了一个名为“小猪吃苹果”的游戏...
装饰模式是一种结构型设计模式,它允许我们向一个对象动态地添加新的行为或责任,而无需修改该对象的源代码。在C#中,装饰模式是通过创建一个包装类(Decorator),该包装类实现了与被装饰对象相同的接口,并持有被...
【装饰模式】是一种设计模式,源自Erich Gamma等人编写的《设计模式:可重用面向对象软件的基础》一书。这种模式在Swing开发中尤为常见,用于增强或改进现有对象的功能,尤其在Web应用程序中,如Java的J2EE环境,...
装饰模式是一种设计模式,属于结构型模式,其主要目的是在不改变对象本身的基础上,通过向对象添加新的行为或属性来扩展其功能。这种模式遵循“开闭原则”,即对扩展开放,对修改关闭。 在装饰模式中,有四个关键...
装饰模式是一种结构型设计模式,它允许在运行时给对象添加新的行为或责任,而无需修改对象的源代码。在Java中,装饰模式通常通过继承和组合来实现,提供了比子类化更灵活的方式来扩展对象的功能。 装饰模式的核心...
装饰模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在软件工程中非常常见,因为它提供了灵活性,使得我们可以独立于对象的组合来扩展功能。 在C++中,装饰...
装饰模式是一种结构型设计模式,它允许在运行时动态地给对象添加新的行为或属性,而不必修改原有类的代码。这种模式的核心在于装饰者和组件接口的统一,使得装饰者可以替代原对象并添加额外的功能。在"设计模式之...
装饰模式(Decorator)是软件设计领域中一种非常实用的结构型设计模式,它允许我们向一个对象添加新的行为或责任,而无需修改该对象的源代码。在C++编程语言中,装饰模式常用于动态地扩展类的功能,使得类的行为在...
装饰模式是一种设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在不违背开闭原则(对扩展开放,对修改关闭)的前提下,提供了灵活的扩展机制。装饰模式通常用于为已有对象添加...
装饰模式(Decorator Pattern)是设计模式中的一种结构型模式,它在不改变原有对象的基础上,通过添加额外的职责来扩展对象的功能。在C#中,装饰模式尤其适用于那些需要动态地增加或减少对象功能的情况,避免了使用...
装饰模式是一种设计模式,它允许在不改变对象自身的情况下,动态地给对象添加新的行为或职责。这种模式常用于在不修改源代码的情况下扩展对象的功能,或者为对象提供额外的职责。在本例中,"项目经理接到一个项目,...
装饰模式是一种设计模式,它允许我们在不改变对象本身的情况下,为对象添加新的行为或属性,从而扩展其功能。这种模式遵循“开闭原则”,即对扩展开放,对修改关闭,这意味着我们可以灵活地增加一个对象的功能,而...
装饰模式是一种结构型设计模式,它允许我们向现有的对象添加新的功能,同时又不破坏其原有的结构。在C#中,装饰模式常用于在运行时动态地改变对象的行为,而无需修改原始类的代码。这种模式的核心在于装饰者类与被...
装饰模式是一种设计模式,它允许在运行时向对象添加新的行为或职责,而无需修改对象的源代码。这种模式在软件工程中非常有用,因为它提供了灵活性,使得代码可以在不破坏封装性的前提下进行扩展。 在"实验九:装饰...
装饰模式是一种设计模式,它允许在不修改对象本身的情况下,通过包装(或“装饰”)对象来动态地扩展其功能。在面向切面编程(Aspect Oriented Programming, AOP)中,装饰模式常被用来实现在运行时向目标对象添加...
装饰模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式通常用于保持对象的原始类结构不变,同时增强其功能。HeadFirst 设计模式系列书籍以其生动有趣的插图和...
装饰模式是一种结构型设计模式,它允许我们向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在不违背开闭原则(对扩展开放,对修改关闭)的前提下,提供了灵活的扩展机制。在《Head First设计模式》一书...
装饰模式是一种结构型设计模式,它是面向对象设计中用来动态添加或修改对象功能的一种方法。在软件工程中,装饰模式允许我们向一个现有的对象添加新的行为或职责,同时又不改变其原有的结构,从而实现对类的功能扩展...
装饰模式是一种设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在Java等面向对象编程语言中非常常见,因为它提供了灵活性,使得扩展对象的功能变得容易且优雅。在这个"装饰...