`
指尖残血
  • 浏览: 2974 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多

本文参考:《修炼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),该包装类实现了与被装饰对象相同的接口,并持有被...

    用装饰模式装饰HttpServletRequest对象

    【装饰模式】是一种设计模式,源自Erich Gamma等人编写的《设计模式:可重用面向对象软件的基础》一书。这种模式在Swing开发中尤为常见,用于增强或改进现有对象的功能,尤其在Web应用程序中,如Java的J2EE环境,...

    装饰模式——装饰模式.doc

    装饰模式是一种设计模式,属于结构型模式,其主要目的是在不改变对象本身的基础上,通过向对象添加新的行为或属性来扩展其功能。这种模式遵循“开闭原则”,即对扩展开放,对修改关闭。 在装饰模式中,有四个关键...

    JAVA设计模式之装饰模式代码

    装饰模式是一种结构型设计模式,它允许在运行时给对象添加新的行为或责任,而无需修改对象的源代码。在Java中,装饰模式通常通过继承和组合来实现,提供了比子类化更灵活的方式来扩展对象的功能。 装饰模式的核心...

    设计模式 - 装饰模式(C++实例)

    装饰模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在软件工程中非常常见,因为它提供了灵活性,使得我们可以独立于对象的组合来扩展功能。 在C++中,装饰...

    设计模式之装饰模式:以售卖咖啡为例

    装饰模式是一种结构型设计模式,它允许在运行时动态地给对象添加新的行为或属性,而不必修改原有类的代码。这种模式的核心在于装饰者和组件接口的统一,使得装饰者可以替代原对象并添加额外的功能。在"设计模式之...

    设计模式C++学习之装饰模式(Decorator)

    装饰模式(Decorator)是软件设计领域中一种非常实用的结构型设计模式,它允许我们向一个对象添加新的行为或责任,而无需修改该对象的源代码。在C++编程语言中,装饰模式常用于动态地扩展类的功能,使得类的行为在...

    装饰模式代码示例

    装饰模式是一种设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在不违背开闭原则(对扩展开放,对修改关闭)的前提下,提供了灵活的扩展机制。装饰模式通常用于为已有对象添加...

    C#设计模式之Decorator 装饰模式

    装饰模式(Decorator Pattern)是设计模式中的一种结构型模式,它在不改变原有对象的基础上,通过添加额外的职责来扩展对象的功能。在C#中,装饰模式尤其适用于那些需要动态地增加或减少对象功能的情况,避免了使用...

    利用装饰模式,实现编写项目经理接到一个项目,需要完成编码

    装饰模式是一种设计模式,它允许在不改变对象自身的情况下,动态地给对象添加新的行为或职责。这种模式常用于在不修改源代码的情况下扩展对象的功能,或者为对象提供额外的职责。在本例中,"项目经理接到一个项目,...

    装饰模式小应用

    装饰模式是一种设计模式,它允许我们在不改变对象本身的情况下,为对象添加新的行为或属性,从而扩展其功能。这种模式遵循“开闭原则”,即对扩展开放,对修改关闭,这意味着我们可以灵活地增加一个对象的功能,而...

    C# 装饰模式实例

    装饰模式是一种结构型设计模式,它允许我们向现有的对象添加新的功能,同时又不破坏其原有的结构。在C#中,装饰模式常用于在运行时动态地改变对象的行为,而无需修改原始类的代码。这种模式的核心在于装饰者类与被...

    实验九:装饰模式.rar

    装饰模式是一种设计模式,它允许在运行时向对象添加新的行为或职责,而无需修改对象的源代码。这种模式在软件工程中非常有用,因为它提供了灵活性,使得代码可以在不破坏封装性的前提下进行扩展。 在"实验九:装饰...

    装饰模式实现AOP

    装饰模式是一种设计模式,它允许在不修改对象本身的情况下,通过包装(或“装饰”)对象来动态地扩展其功能。在面向切面编程(Aspect Oriented Programming, AOP)中,装饰模式常被用来实现在运行时向目标对象添加...

    HeadFirst 设计模式学习笔记3--装饰模式 Demo

    装饰模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式通常用于保持对象的原始类结构不变,同时增强其功能。HeadFirst 设计模式系列书籍以其生动有趣的插图和...

    装饰模式简单例子

    装饰模式是一种结构型设计模式,它允许我们向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在不违背开闭原则(对扩展开放,对修改关闭)的前提下,提供了灵活的扩展机制。在《Head First设计模式》一书...

    23种设计模式--装饰模式

    装饰模式是一种结构型设计模式,它是面向对象设计中用来动态添加或修改对象功能的一种方法。在软件工程中,装饰模式允许我们向一个现有的对象添加新的行为或职责,同时又不改变其原有的结构,从而实现对类的功能扩展...

    装饰模式生成密码实例

    装饰模式是一种设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在Java等面向对象编程语言中非常常见,因为它提供了灵活性,使得扩展对象的功能变得容易且优雅。在这个"装饰...

Global site tag (gtag.js) - Google Analytics