`
bcyy
  • 浏览: 1809549 次
文章分类
社区版块
存档分类
最新评论

设计模式学习--装饰者模式(Decorator Pattern)

 
阅读更多

设计模式学习--装饰者模式(Decorator Pattern)

2013年5月19日 天气:阴天下雨
不停脚步继续学习设计模式
小巫在呐喊:啊、啊、啊、啊、啊

什么是装饰者模式?

其实我们用Java I/O的时候已经用到过了,只是可能不知道这就是设计模式,在后面有一个设计自己的装饰者模式,再介绍吧。

HeadFirst这样定义:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

新的设计原则

对扩展开发,对修改关闭

写一写要点

1. 继承属于扩展形式之一,但不见得达到弹性设计的最佳方式。
2. 在我们的设计中,应该允许行为可以被扩展,而无须修改现有的代码。
3. 组合和委托可用于在运行时动态加上新的行为。
4. 除了继承,装饰者模式也可以让我们扩展行为。
5. 装饰者模式意味着一群装饰者类,这些类用来包装具体组件。
6. 装饰者类反映出被装饰的组件类型(事实上,他们具有相同的类型,都经过接口或继承实现)
7. 装饰者可以在被装饰者的行为与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
8. 你可以用无数个装饰者包装一个组件。
9. 装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型。
10. 装饰者会导致设计中出现许多的小对象,如果过度使用,会让程序变得很复杂。




装饰者模式例子:星巴兹咖啡

怎么开始?
写下星巴兹的代码:
package decoratorPattern;
/**
 * 2013/5/19
 * @author wwj
 * 饮料抽象类
 */
public abstract class Beverage {
	String description = "Unknown Beverage"; //饮料描述
	
	public String getDescription() {	//得到饮料描述
		return description;
	}
	
	public abstract double cost();	//抽象方法,用于计算饮料价格
}


package decoratorPattern;

/**
 * 2013/5/19
 * @author wwj
 * 调料抽象类:代表装饰者
 */
public abstract class CondimentDecorator extends Beverage {

	@Override
	public double cost() {
		return 0;
	}
	
	/**
	 * 所有的调料装饰者都必须重新实现getDescription()方法。
	 */
	public abstract String getDescription();

}


写饮料的代码:
这里有四种:Epresso、HouseBlend、DarkRoast、Decat

package decoratorPattern;

/**
 * 2013/5/19
 * @author wwj
 * 浓缩咖啡,一种饮料
 */
public class Espresso extends Beverage {
	public Espresso() {
		description = "Espresso";
	}
	
	@Override
	public double cost() {
		return 1.99;
	}

}

package decoratorPattern;

/**
 * 2013/5/19
 * @author wwj
 * 综合饮料
 */
public class HouseBlend extends Beverage {
	public HouseBlend(){
		description = "House Blend Coffee";
	}
	
	@Override
	public double cost() {
		return .89;
	}

}

package decoratorPattern;

/**
 * 2013/5/19
 * @author wwj
 * 深培咖啡
 */
public class DarkRoast extends Beverage {
	public DarkRoast(){
		description = "DarkRoast";
	}
	@Override
	public double cost() {
		return .99;
	}

}

package decoratorPattern;

/**
 * 2013/5/19
 * @author wwj
 * 低咖啡因
 */
public class Decat extends Beverage {
	public Decat(){
		description = "Decat";
	}
	@Override
	public double cost() {
		return 1.05;
	}

}


写调料的代码
这里有三种调料:Mocha、Soy、Whip
package decoratorPattern;

/**
 * 2013/5/19
 * @author wwj
 * 具体装饰者:摩卡
 */
public class Mocha extends CondimentDecorator {
	//定义一个实例变量记录饮料,也就是被装饰者
	Beverage beverage;
	
	/**
	 * 用来把被装饰者记录到实例变量中去
	 * @param beverage
	 */
	public Mocha(Beverage beverage) {
		this.beverage = beverage;
	}

	
	/**
	 * 这里利用委托的做法,得到一个叙述,然后在其后加上附加的叙述
	 */
	@Override
	public String getDescription() {
		return beverage.getDescription() + ", Mocha";
	}
	
	/**
	 * 要计算Mocha饮料的价钱。首先把调用委托给被装饰对象,以计算价钱,然后再加上Mocha的价钱,得到最后结果
	 */
	public double cost() {
		return .20 + beverage.cost();
	}
}

package decoratorPattern;

/**
 * 2013/5/19
 * @author wwj
 * 豆浆,一种配料
 */
public class Soy extends CondimentDecorator {
	Beverage beverage;
	
	
	public Soy(Beverage beverage) {
		this.beverage = beverage;
	}


	@Override
	public String getDescription() {
		return beverage.getDescription() + ",Soy";
	}
	
	public double cost() {
		return .15 + beverage.cost();
	}

}

package decoratorPattern;

/**
 * 2013/5/19
 * @author wwj
 * 奶泡,一种配料
 */
public class Whip extends CondimentDecorator {
	Beverage beverage;
	
	
	public Whip(Beverage beverage) {
		this.beverage = beverage;
	}


	@Override
	public String getDescription() {
		return beverage.getDescription() + ",Whip";
	}
	
	public double cost() {
		return .10 + beverage.cost();
	}

}

现在可以供应咖啡了
package decoratorPattern;

/**
 * 测试类,供应咖啡
 * @author wwj
 *
 */
public class StarbuzzCoffee {

	public static void main(String[] args) {
		//订一杯Espresso,不需要调料,打印出它的描述与价钱
		Beverage beverage = new Espresso();
		System.out.println(beverage.getDescription() + " $" + beverage.cost());
		
		Beverage beverage2 = new DarkRoast();
		beverage2 = new Mocha(beverage2);	//用Mocha装饰它
		beverage2 = new Mocha(beverage2);	//用第二个Mocha装饰它
		beverage2 = new Whip(beverage2);	//用Whip装饰它
		System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
		
		
		Beverage beverage3 = new HouseBlend();
		beverage3 = new Soy(beverage3);
		beverage3 = new Mocha(beverage3);
		beverage3 = new Whip(beverage3);
		System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
	}
}
实验结果如下:

Espresso $1.99
DarkRoast, Mocha, Mocha,Whip $1.49
House Blend Coffee,Soy, Mocha,Whip $1.34

如果觉得看得不够爽,买办HeadFirst设计模式吧,就算小巫是新手也还是觉得这本书值得一卖,图文并茂,看起来不会累。


刚开始的时候已经说过Java中使用装饰者模式的I/O
下面就扩展一下它的行为:将大写字符转换为小写字符
package javaIo;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/*
 * 编写自己的Java I/O装饰者
 */
public class LowerCaseInputStream extends FilterInputStream {

	protected LowerCaseInputStream(InputStream in) {
		super(in);
	}
	/**
	 * 针对字节
	 */
	public int read() throws IOException {
		int c = super.read();
		return (c == -1 ? c : Character.toLowerCase((char) c));
	}
	
	/**
	 * 针对字节数组
	 */
	public int read(byte[] b, int offset, int len) throws IOException {
		int result = super.read(b, offset, len);
		for(int i = offset; i < offset + result; i++) {
			b[i] = (byte) Character.toLowerCase((char)b[i]);
		}
		return result;
	}

}


package javaIo;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class InputTest {
	public static void main(String[] args) throws IOException{
		int c;
		try {
			//设置FileInputStream,先用BufferedInputStream装饰它,再用我们崭新的
			//LowerCaseInputStream过滤器装饰它
			InputStream in =
				new LowerCaseInputStream(
						new BufferedInputStream(new FileInputStream("D:/test.txt")));
			while((c = in.read()) >= 0) {
				System.out.print((char)c);
			}
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

测试结果:
i know the decorator pattern

ok,装饰者模式就是这样子啦,搞清楚装饰者和被装饰者之间的关系,也没啥不好理解的。下一个设计模式:工厂模式,比较常用的一个模式。今天是星期日,宝贵的周末时间就要没了,可能就不会想这两天那么频繁地发表博客了,不过有空一定会继续学习的。









分享到:
评论

相关推荐

    C#设计模式-吕震宇

    C#设计模式(12)-Decorator Pattern C#设计模式(11)-Composite Pattern C#设计模式(10)-Adapter Pattern C#设计模式(9)-Prototype Pattern C#设计模式(8)-Builder Pattern C#设计模式(7)-Singleton...

    设计模式之装饰模式(Decorator Pattern)

    动态地给一个对象添加一些额外的职责。就扩展功能而言,它比生成子类方式更为灵活。

    Head First 设计模式 (三) 装饰者模式(decorator pattern) C++实现

    Head First 设计模式 (三) 装饰者模式(decorator pattern) C++实现 VS2012 下通过

    design-pattern-java.pdf

    设计模式趣味学习(复习) 设计模式趣味学习(复习) 设计模式与足球(一) 设计模式与足球(二) 设计模式与足球(三) 设计模式与足球(四) 设计模式综合应用实例 设计模式综合应用实例 多人联机射击游戏 多人...

    设计模式精解-GoF 23种设计模式解析附C++实现源码

    设计模式精解-GoF 23种设计模式解析附C++实现源码 AbstractFactory模式、Adapater模式、Composite模式、Decorator模式、Factory模式、Observer模式、Strategy模式、Template模式

    36种最新设计模式整理

    36种最新设计模式整理 Design Pattern: Simple Factory 模式 Design Pattern: Abstract Factory 模式 Design Pattern: Builder 模式 Design Pattern: Factory Method 模式 Design Pattern: Prototype 模式 ...

    C#版 24种设计模式

    备忘录模式(Memento Pattern) 策略模式(Strategy Pattern) 抽象工厂模式(Abstract Factory Pattern) 代理模式(Proxy Pattern) ...装饰模式(Decorator Pattern) 状态模式(State Pattern) 组合模式(Composite Pattern)

    用Java实现23种设计模式

    用Java实现23种设计模式 1. 创建型模式 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern)...

    Java24种设计模式,Java24种设计模式,24种设计模式,学会了这24种设计模式,可以打遍天下无敌手,设计模式非常重要

    13、装饰模式DECORATOR PATTERN 14、迭代器模式ITERATOR PATTERN 15、组合模式COMPOSITE PATTERN 16、观察者模式OBSERVER PATTERN 17、责任链模式 18、访问者模式VISITOR PATTERN 19、状态模式 20、原型模式 21...

    java设计模式源码-DesignPattern:设计模式(Java实现源码)

    java 设计模式 源码 欢迎访问DesignPattern项目 ...装饰器模式(decoratorPattern) 外观模式(facadePattern) 享元模式(flyweightPattern) 代理模式(proxyPattern) 责任链模式(chainPattern) 命令模式(commandPatter

    单例模式源码java-DesignPattern:在个人自学阶段的23种设计模式代码的全部实现,全部使用Java编写,其中还包括各个设计模式在

    在个人自学阶段的23种设计模式代码的全部实现,全部使用Java编写,其中还包括各个设计模式在源码中的使用,每种设计模式都举了一个简单的小例子来进行实现,并加以注释 包名解释 一、DesignPattern 1.1 创建型模式 ...

    C++设计模式(Design Pattern)范例源代码

    23种设计模式(Design Pattern)的C++实现范例,包括下面列出的各种模式,代码包含较详细注释。另外附上“设计模式迷你手册.chm” 供参考。 注:项目在 VS2008 下使用。 创建型: 抽象工厂模式(Abstract Factory) ...

    C#设计模式.PDF

    C#设计模式(12)-Decorator Pattern 101 一、 装饰(Decorator)模式 101 二、 装饰模式的结构 102 三、 装饰模式示例性代码 103 四、 装饰模式应当在什么情况下使用 106 五、 装饰模式实际应用的例子 106 六、 ...

    33种JAVA设计模式DEMO

    装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) 3 行为型模式 这些设计模式特别关注对象之间的通信。 责任链模式(Chain of ...

    设计模式PPT

     装饰者模式(Decorator Pattern)  外观模式(Facade Pattern)  享元模式(Flyweight Pattern)  代理模式(Proxy Pattern) 行为型模式用来对类或对象怎样交互和怎样分配职责进行描述,主要包含以下11种...

    C#设计模式大全

    C#设计模式(12)-Decorator Pattern 一、 装饰(Decorator)模式 二、 装饰模式的结构 三、 装饰模式示例性代码 四、 装饰模式应当在什么情况下使用 五、 装饰模式实际应用的例子 六、 使用装饰模式的优点和...

    C#设计模式_设计模式_C#_

    装饰模式(Decorator Pattern) 9. 组合模式(Composite Pattern) 10. 外观模式(Facade Pattern) 11. 享元模式(Flyweight Pattern) 12. 代理模式(Proxy Pattern) 行为型: 13. 模板方法(Template Method) 14. 命令...

    Pattern-Decorator-Java:设计模式工作坊——装饰者模式

    您必须实现装饰器模式,以便可以在运行时添加提到的服务。 作为开发服务如何工作的示例,在运行时创建一个用加密和缓存装饰的 JSON 策略,以及一个带有日志记录的 XML 策略。 请记住,您必须提供源代码和详细说明所...

    CoreJava-DesignPattern

    创意设计模式 -- Abstract Factory - Done -- Builder - Done -- Factory Method -- Object Pool -- Prototype - Done -- Singleton - Done 结构设计模式 -- Adapter -- Bridge -- Composite -- Decorator - Done ...

Global site tag (gtag.js) - Google Analytics