java23种设计模式之装饰器模式

来源:互联网 发布:最火的网络用语 编辑:程序博客网 时间:2024/06/05 07:43

首先我们在学习装饰器模式的时候,先要了解它的作用:为一个对象增加额外的增强功能,相当于美女穿新衣,美女更漂亮了偷笑

使用条件:

1.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
2.处理那些可以撤销的职责
3.当不能采用生成子类的方式进行扩充时

结构图:


构件的组成:

抽象组件角色(Component):定义一个对象接口,以规范准备接受附加责任的对象,

即可以给这些对象动态地添加职责。

具体组件角色(ConcreteComponent) :被装饰者,定义一个将要被装饰增加功能的类。

可以给这个类的对象添加一些职责

抽象装饰器(Decorator):维持一个指向构件Component对象的实例,

并定义一个与抽象组件角色Component接口一致的接口

具体装饰器角色(ConcreteDecorator):向组件添加职责。

装饰模式的特点:

  (1) 装饰对象和真实对象有相同的接口。这样客户端对象就可以以和真实对象相同的方式和装饰对象交互。
  (2) 装饰对象包含一个真实对象的索引(reference)
  (3) 装饰对象接受所有的来自客户端的请求。它把这些请求转发给真实的对象。

  (4) 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

java中比较常用的还是IO流


 FilterInputStream和FilterOutputStream

首先,这两个都分别是InputStream和OutputStream的子类。而且,FilterInputStream和FilterOutputStream是具体的子类,实现了InputStream和OutputStream这两个抽象类中为给出实现的方法。

但是,FilterInputStream和FilterOutputStream仅仅是“装饰者模式”封装的开始,它们在各个方法中的实现都是最基本的实现,都是基于构造方法中传入参数封装的InputStream和OutputStream的原始对象。

BufferedInputStream/BufferedOutputStream

先说说这个最简单的一对,BufferedInputStream和BufferedOutputStream。顾名思义,Buffered就是缓冲了的。在BufferedInputStream和BufferedOutputStream中,都额外实现了byte数组做buffer。

我们知道在父类FilterInputStream和FilterOutputStream类中,已经在构造方法时封装了原始的InputStream或者OutputStream对象。

在我们使用BufferedInputStream和BufferedOutputStream来进行read()和write()调用的时候,并不一定直接对封装的InputStream或者OutputStream对象进行操作,而是要经过缓冲处理。

在BufferedInputStream的read()中,实际上是一次读取了多个字节到缓冲数组,而非一次只读取一个。后续的read()操作可以直接从数组中获取字节,而不必再次调用封装的InputStream对象的read()操作。这样做其实在一定情况下可以减少底层的read调用次数,降低成本开销,提高了效率。

在BufferedOutputStream中也是一样,它的write()会先把数据写到缓冲数组中,直到数据达到了某个特定的限额,再调用write()的时候回真正调用到封装的OutputStream对象的write()方法。

而DataInputStream/DataOutputStream这一对实际上所做的也就是这两个接口所定义的方法。再DataInputStream/DataOutputStream中,这些方法做了拼接和拆分字节的工作。通过这些方法,我们可以方便的读取、写出各种我们实际所面对的类型的数据,而不必具体去在字节层面上做细节操作。

代码:

public class IoTest_BufferedReader {public static void main(String[] args) throws IOException {readFile("c:\\a.txt");}private static void readFile(String path) throws IOException {Reader read = new FileReader(path);BufferedReader bufferedReader = new BufferedReader(read);BufferedReader br = new MyQutoBufferedReader2(bufferedReader);br = new MyLineBufferedReader2(br);String line = null;while ((line = br.readLine()) != null) {System.out.println(line);}}}// quotation 引号class MyQutoBufferedReader2 extends BufferedReader {private BufferedReader bufferedReader;public MyQutoBufferedReader2(BufferedReader bufferedReader) {super(bufferedReader);this.bufferedReader = bufferedReader;}public String readLine() throws IOException {String line = super.readLine();if (line != null) {return "\"" + line + "\"";} else {return null;}}}class MyLineBufferedReader2 extends BufferedReader {private BufferedReader bufferedReader;public MyLineBufferedReader2(BufferedReader bufferedReader) {super(bufferedReader);this.bufferedReader = bufferedReader;}int count;@Overridepublic String readLine() throws IOException {String line = super.readLine();if (line != null) {count++;return count + ":" + line;} else {return null;}}}
总结:

1)使用装饰器设计模式设计类的目标是: 不必重写任何已有的功能性代码,而是对某个基于对象应用增量变化。 

2) 装饰器设计模式采用这样的构建方式: 在主代码流中应该能够直接插入一个或多个更改或“装饰”目标对象的装饰器,

同时不影响其他代码流。

3) Decorator模式采用对象组合而非继承的手法,实现了在运行时动态的扩展对象功能的能力,

而且可以根据需要扩展多个功能,避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。

同时它很好地符合面向对象设计原则中“优先使用对象组合而非继承”和“开放-封闭”原则。

也许装饰器模式最重要的一个方面是它的超过继承的能力。“问题”部分展现了一个使用继承的子类爆炸。

基于装饰器模式的解决方案,UML类图展现了这个简洁灵活的解决方案。


这篇文章的例子举的很通透:http://www.bkjia.com/Androidjc/1195510.html


原创粉丝点击