java 装饰器模式

http://eneasy.iteye.com/blog/174840

http://www.cnblogs.com/ikuman/archive/2013/01/29/2877913.html


1.意图: 

    在一个对象的外围创建一个称为装饰器的封装,动态地给这个对象添加一些额外的功能。 

2.类图: 
     

3.原理: 
      在一个对象的外围创建一个称为装饰器的封装,动态地给这个对象添加一些额外的功能。以对客户端透明的方式扩展对象的功能。 
       装饰器模式又称为包裹模式(wrapper),因为一个具体装饰器都将下一个具体装饰器或具体构件类包裹起来。如有三个装饰器类Decorator1, Decorator2, Decorator3,它们的典型的创建过程为new Decorator1(new Decorator2(new Decorator3(new ConcreteComponent()))). 

    这样Decorator1包裹了Decorator2,Decorator2包裹了Decorator3,Decorator3包裹了ConcreteComponent对象,每一层包裹都提供了新的功能。如图: 




interface Person {
	void doCoding();
}

class Employee implements Person {
	public void doCoding() {
		System.out.println("程序员写程序");
	}
}

abstract class Manager implements Person {
	public abstract void doCoding();
}

class ManagerA extends Manager {
	private Person person;
	public ManagerA(Person person) {
		super();
		this.person = person;
		
	}
	
	public void doCoding() {
		doEarlyWork();
		person.doCoding();
	}
	
	public void doEarlyWork() {
		System.out.println("项目经理A做需求分析");
		System.out.println("项目经理A做架构设计");
	}
}

class ManagerB extends Manager {
	private Person person;
	public ManagerB(Person person) {
		super();
		this.person = person;
		
	}
	
	public void doCoding() {
		
		person.doCoding();
		doEndWork();
	}
	
	public void doEndWork() {
		
		System.out.println("项目经理B做收尾工作");
	}
}

public class Decorator {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Person employee = new Employee();
		employee = new ManagerA(employee);
		employee = new ManagerB(employee);
		
		employee.doCoding();  
	}

}

项目经理A做需求分析
项目经理A做架构设计
程序员写程序
项目经理B做收尾工作


优点: 

    装饰器与继承的目的都是扩展对象的功能,但装饰器提供了比继承更大的灵活性,可以动态的决定是“粘上”还是“去掉”一个装饰。 
      通过使用不同的具体装饰类和这些类的排列组合,可以创建出很多不同行为的组合。 

    缺点: 

    装饰器比继承关系使用更少的类,但比继承关系使用更多的对象,更多的对象会使查错变得更困难,特别是这些对象看上去很像的时候。 

实际应用中的例子:java i/o




还是head first中的图清晰明了



第二层是concretcomponents和abstract decorator

concretcomponents是实现具体或者核心任务的类(负责实际将磁盘上的数据读入到内存), concret decorators只是在这个核心任务类的基础上做些前处理或者后处理的事情

第三层是concret decorators,实现的是对某一个concret component和其他concrete decorator的包装或者修饰

比如,InputStream in = new  BufferedInputStream(new FileInputStream("txt"));

FileInputStream是一个concrete component, 其作用是读取磁盘上的文件,将其的一个对象给BufferedInputStream对象的一个成员变量,其中BufferedInputStream是一个concrete decorator, 由具体的修饰类对具体成分类进行“后处理”或者“预处理”,其作用就是调用FileInputStream读取磁盘上的文件,但是在BufferedInputStream内部使用缓冲区,加速文件读取。

也可以写成这样的形式

InputStream in = new LineNumberInputStream(new BufferedInputStream(new FileInputStream("tt")));

具体修饰类可以多次“包装”


可以自己实现一个具体修饰类

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


//concrete decorator
class LowerInputStream extends FilterInputStream {
	public LowerInputStream(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 = 0; i < len; ++i) {
			b[i] = (byte)Character.toLowerCase((char)b[i]);
		}
		
		return result;
	}
}

public class Decorator {

	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		InputStream in = new LowerInputStream(new BufferedInputStream(new FileInputStream("tt")));
		
		int c;
		while((c = in.read()) >=0) {
			System.out.print((char)c);
		}
	}

}


上面分析的是面向字节流的类,接下来分析面向字符流的

其中最重要的是InputStreamReader,起到将字节流按照指定编码改变为字符流的作用


从上图可以看到,StreamDecoder是一个适配器,将InputStream字节流,按照Reader的接口改变成字符流

其实InputStreamReader也可以看做一个适配器,将StreamDecoder,按照Reader接口进行改装




如果把InputStreamReader看做一个具体component,那么BufferedReader就是一个具体的修饰类

所以,我们通常这样写

BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("D:/cplus/norm/norm/exp"), "UTF-8"));




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值