设计模式初探-装饰模式(一)

2014-11-24 03:22:01 · 作者: · 浏览: 3

装饰模式(DECORATOR模式),又称包装器Wrapper,属于对象结构型模式,用于动态地给一个对象添加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。它通过使用对象之间的关联关系取代类之间的继承关系,引入的装饰类既可以调用被装饰类的方法,还可以添加新的业务逻辑,以达到扩充被装饰类的功能。装饰模式和适配器模式虽然都称为包装器,但两者还是不同的。装饰模式只是在原有对象的基础上增加新的职责,而不改变对外提供的接口。适配器模式用于解决接口之间的不兼容问题,必然会改变对外提供的接口。

一、使用场景

1、在不影响其他对象的情况下,以动态,透明的方式给单个对象添加职责。装饰模式采用对象组合而非类继承方式扩展功能,所以对于需要扩充的对象可以动态添加,切换,删除相应的职责而不影响其他对象。

2、处理那些可以撤销的职责,对于需要某项职责的对象只需关联相应的装饰对象即可。

3、当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时。一种情况是系统中存在大量独立的扩展,为支持每一种扩展或者扩展之间的组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏或类不能被继承,比如java中类定义为final类。

二、UML图

装饰模式uml

三、Java实现

package study.patterns.decorator;

/**
 * 装饰模式:降低系统的耦合度,可以动态增加或删除对象的职责,
 * 并使得需要装饰的具体构件类和具体装饰类可以独立变化,
 * 以便增加新的具体构件类和具体装饰类。
 * 如果需要在原有系统中增加一个新的具体构件类或者新的具体装饰类,
 * 无须修改现有类库代码,只需将它们分别作为抽象构件类或者抽象装饰类的子类即可. 
 * @author qbg
 */
public class DecoratorPattern {
	public static void main(String[] args) {
		String test = "test123";
		//使用默认装饰类和不使用装饰类效果一样
		IStream dStream = new StreamDecorator(new MemoryStream());
		dStream.write(test);
		String r0 = dStream.read();
		System.out.println("======使用默认装饰类:"+r0);
		//使用压缩装饰类
		IStream cStream = new CompressingStream(new MemoryStream());
		cStream.write(test);
		String r1 = cStream.read();
		System.out.println("======使用压缩装饰类:"+r1);
		//使用ASCII装饰类
		IStream aStream = new ASCII7Strem(new FileStream()); 
		aStream.write(test);
		String r2 = aStream.read();
		System.out.println("======使用ASCII装饰类:"+r2);
		//先使用ASCII装饰类进行编码转换,然后使用压缩装饰类进行压缩
		IStream caStream = new ASCII7Strem(new CompressingStream(new FileStream()));
		caStream.write(test);
		String r3 = caStream.read();
		System.out.println("======使用ASCII和压缩装饰类:"+r3);
	}
}
/**
 * I/O流接口
 */
interface IStream{
	/**
	 * 读取流
	 */
	public String read();
	/**
	 * 写入流
	 */
	public void write(String str);
}
/**
 * 流介质为内存型
 */
class MemoryStream implements IStream{
	private String stream;
	@Override
	public String read() {
		System.out.println("从内存中读取流...");
		return stream;
	}

	@Override
	public void write(String stream) {
		System.out.println("往内存中写入流...");
		this.stream = stream;
	}
}
/**
 * 流介质为文件系统 
 */
class FileStream implements IStream{
	private String stream;
	@Override
	public String read() {
		System.out.println("从文件中读取流...");
		return stream;
	}

	@Override
	public void write(String stream) {
		System.out.println("往文件中写入流...");
		this.stream = stream;
	}

}
/**
 * 流装饰默认实现类
 */
class StreamDecorator implements IStream{
	private IStream stream;
	public StreamDecorator(IStream stream){
		this.stream = stream;
	}
	@Override
	public String read() {
		return this.stream.read();
	}
	@Override
	public void write(String stream) {
		this.stream.write(stream);
	}
}
/**
 * 将流数据转换为7位ASCII码
 */
class ASCII7Strem  extends StreamDecorator{
	public ASCII7Strem(IStream stream) {
		super(stream);
	}
	@Override
	public void write(String stream) {
		super.write(toAscii7(stream));
	}
	/*
	 * 额外职责
	 */
	private String toAscii7(String stream){
		System.out.println("将数据转换为7位ASCII码");
		return "ASCII["+stream+"]";
	}
}
/**
 * 将流数据压缩 
 */
class CompressingStream extends StreamDecorator{

	public CompressingStream(IStream stream) {
		super(stream);
	}
	@Override
	public void write(String stream) {
		super.write(com