`
dalongJDK
  • 浏览: 15746 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

IO流所涉及到的Decorator设计模式

阅读更多
       前段时间的时候总结了一篇关于IO流所用到的Decorator设计模式的文章,今天再看一遍,感觉收获些小许,嘿嘿:
首先看下面两条语句:
InputStream  input = new BufferedInputStream(new FileInputStream(“1.txt”)) 
InputStream  input= new DataIputStream(new FileInputStream(“1.txt”))

       以前就见过好多这种结构,把字节封装成字符串等等其他的形式,或者给读取文件增加一个缓冲区,这种输入输出流有很多种组合,那么他们是遵循那一种规律的呢?原来这都是Decorator的功劳,Decorator,装饰模式,又名Wrapper,此模式的目的在于动态扩展一个类的功能。
        当我们要拓展一个类的功能,我们很自然的想到从这个类派生出一个子类,附加一些方法,就实现了类的拓展,事实上这正是面向对象的威力:复用基类的代码,并且扩展出功能更强大的子类。
        但是这种扩展时静态的,在编译的时候已经确定了子类的功能,试想一下我们需要的输入功能:文件输入,原始类型数据输入,缓冲输入,字符串输入。。。如果同时需要文件输入和缓冲输入的功能,就必须再次派生一个新类,这样组合下来,子类的数量会相当可观。
        这种静态静态组合继承严重影响了可扩展性,试想,某一天需要加入一个新的输入流,比如ZipInputStream,配合其他的功能又需要写一系列的子类,这不仅仅是需要劳动力的问题和时间,而且他是不可以动态的加载进去。
        那么怎么解决由于不同功能的组合将派生出大量的子类呢,Decorator模式实现了动态扩展,即在运行时动态地给一个类“装饰”上某些功能。
        同时它是给对象的装饰,不是给类的装饰,也就是说没加修饰之前他们两的没有什么关系,如果说有关系的话,那就是共同继承一个父类吧,这一点可以参考动态加载的class.forname(),class生成之后因为class.forname()才把他加载进去,但静态加载在初始化的时候就已经确定了对象之间的关系了。
        比如一个FileInputStream 的实例已经生成,现在要给它“装上”缓冲的功能,就把它“装饰”成BufferedInputStream,这样这个FileInputStream就动态具备了缓冲功能。在java中,可以用下面的代码:
InputStream inp = new BufferedInputStream(new FileInputStream());

而这个缓冲功能是在程序运行时动态加上去的。
Java的IO包共有4类重要的输出流:InputStream,OutputStream,Reader,Writer。InputStream和Reader类似,但Reader可以正确转换字符编码,同理,OutputStream和Writer类似;

根据今天看的IO内部部分代码,现在写出一个山寨版的Decorator模式的IO:
一、编写一个Work类,这个类相当于IO里面的龙头老大InputStream,是一个抽象类,代码如下:
package oop.kanglong.testIO2;

public abstract class Work {

	public abstract void paint();

}

二 、编写一个Parent类,这个类相当于IO里面的FilterInputStream,这个类继承了Work类,代码如下:
package oop.kanglong.testIO2;

public class Parent extends Work {
	protected Work work;
	protected Parent(Work work) {
		this.work = work;
	}
	public void paint() {
		work.paint();
	}
}

三,编写一个Son类,这个类就相当于IO里面的FileInputStream,这个类继承了Work类,代码如下:
package oop.kanglong.testIO2;
public class Son extends Work {
	public void paint() {
		System.out.println("儿子正在写作业!!!");
	}
}

四、编写一个修饰Son的修饰Mother类,这个类相当于IO里面的BufferedInputStream,这个类继承了Parent类,代码如下:
package oop.kanglong.testIO2;

public class Mother extends Parent {
	protected Mother(Work work) {
		super(work);
	}
	public void paint() {
       System.out.println("妈妈在厨房做菜!!!");
       super.paint();
       System.out.println("妈妈已经做完菜啦!!!快过来吃饭喽!!!");
	}}

五、还可以编写一个修饰Father类,当然修饰类可以任意多个,这个类相当于IO里面的DataInputStream,这个类继承了Parent类,代码如下:
package oop.kanglong.testIO2;
public class Father extends Parent {
	protected Father(Work work) {
		super(work);
	}
	public void paint() {
		System.out.println("爸爸在客厅看报纸!!!");
		work.paint();
		System.out.println("爸爸看完报纸准备吃饭啦!!!");
	}
}

最后一个就是测试类了:
package oop.kanglong.testIO2;

public class DecoratorTest {
	public static void main(String[] args) {
		Work work = new Son();
		work.paint();
		System.out.println("");
		work = new Mother(work);
		work.paint();
		System.out.println("");
		work = new Father(work);
		work.paint();
	}
}

测试结果为:
儿子正在写作业.

妈妈在厨房做菜。
儿子正在写作业。
妈妈已经做完菜啦。快过来吃饭喽。

爸爸在客厅看报纸。
妈妈在厨房做菜。
儿子正在写作业。
妈妈已经做完菜啦。快过来吃饭喽。
爸爸看完报纸准备吃饭啦。

可以看到,这是一级一级的修饰下去的!!!

小结:
以刚刚那个Demo为例:
          我们创建一个Mother对象并且传入一个Son对象的参数,在初始化的时候,Mother对象的构造函数调用父类的构造方法,其实就是给Work赋一个值:Work work = son;当我们调用Mother的paint方法时,原方法等价于下面方法:
public void paint() {
       System.out.println("妈妈在厨房做菜!!!");
       son.paint();//super.paint();
       System.out.println("妈妈已经做完菜啦!!!快过来吃饭喽!!!");
	}

那就是说可以给原有的son.paint();根据不同的需要增加不同的方法。
现在不难理解下面两条语句了:
work = new Mother(work);
InputStream  input = new BufferedInputStream(new FileInputStream(“1.txt”)) ;


关于Decorator还有其他的一些理解:
Decorator模式和Proxy模式的区别:
          Decorator和Proxy非常相似,Decorator类和Proxy类都包含一个对象的引用,但是他们有各自不同的目标:Decorator是为了给一个对象动态加上某些功能,而Porxy是为了控制对象的访问权限,而且,Decorator必定保持一个被装饰对象的引用,但是Proxy却不一定,因为Proxy是为了检查权限,它可能不直接引用一个对象,而是直接访问一个对象,比如通过InetAddress访问一台远程计算机。

Decorator模式和Adapter模式的区别:
          两者都可以动态改变对象的行为,但是Decorator不会改变对象的接口,比如用BufferedInputStream装饰一个FileInputStream后,它还是一个InputStream,而Adapter不同,他完全改变了对象的原有接口,比如前面提到的用InputStreamReader适配一个FileInputStream后,它就不是InputStream而变成Reader了。

我们可以看到,InputStreamReader不在继承InputStream这个抽象类了。。。

IO流还使用了透明和不透明的Decorator模式:
          所谓透明的Decorator模式是指,使用Decorator装饰后,客户端看不出这个对象和原来的对象有什么区别,比如:
InputStream input = new FileInputStream(“1.txt”);
InputSteam input = new BufferedInputStream(new FileInputstream(“2.txt”));

他们得到的两个input都是InputStream,客户端不能区分它的实际类型,这符合针对抽象编程的思想,可以使代码改动的最小。
String里面的“控制反转”也是用到这种抽象编程的思想:
          注入一个借口到一个action里面,则只需要在applicationcontext里面配置即可,注入的接口对象可以根据不同的实现类,实现不同的功能,这样以后要想更改某种接口的实现的时候,就可以直接在配置文件中更改即可,这样大大降低了类与类之间的耦合度了。。

当然是用不透明的Decorator模式时,客户端就能明确知道对象的实际类型,比如:
BufferedInputStream input = new BufferedInputStream(new FileInputStream(“2.txt”));

        客户端知道要得到的input是一个BufferedInputStream,这样客户端就可以是用一些BufferedInputStream提供的额外的方法,比如readLine(),有时就是为了要使用这些附加功能,这是就用不透明的装饰模式。

最后一个就是Decorator模式的应用了:
         IO流式用的最多的,不过就现在看来,这种思想在Spring里面也用到了不少啊。
  • 大小: 1.7 KB
  • 大小: 8.8 KB
1
0
分享到:
评论
1 楼 Irving_wei 2010-11-18  
举例挺贴切

相关推荐

    Java-从Decorator,Adapter模式看Java/IO

    Java的IO库是一个复杂而强大的系统,其设计思想和实现方式体现了多种设计模式,包括Decorator(装饰者)模式和Adapter(适配器)模式。本文将深入探讨这两个模式在Java/IO中的应用,并通过实例解释它们如何使得Java...

    Java设计模式之-Decorator装饰模式

    装饰模式通常涉及到四个主要角色:Component(组件)、ConcreteComponent(具体组件)、Decorator(装饰者)和ConcreteDecorator(具体装饰者)。 1. Component(组件):定义一个对象接口,所有被装饰的对象以及...

    Java_IO流详解

    Java 的 IO 模型设计非常优秀,它使用 Decorator 模式,用户可以动态装配不同功能的 Stream,以便获得需要的功能。例如,需要一个具有缓冲的文件输入流,则应当组合使用 FileInputStream 和BufferedInputStream。 ...

    java Decorator装饰模式例子

    装饰模式(Decorator Pattern)是设计模式中的一种结构型模式,它允许在运行时给对象添加新的行为或职责,而无需改变对象的类。在Java中,装饰模式通常通过继承和组合来实现,使得代码具有更好的扩展性和灵活性。...

    java-io-decorator.pdf

    Decorator模式在Java IO流中起到了关键作用,它允许在运行时动态地给对象添加新的功能,而无需通过继承的方式创建大量子类。这一模式的核心思想是创建一个装饰者类,它也实现相同的接口,持有被装饰对象的引用,并在...

    JavaIO流详解归纳.pdf

    Java 的 IO 模型设计非常优秀,它使用Decorator 模式,用户可以动态装配不同功能的 Stream,以便获得需要的功能。例如,需要一个具有缓冲的文件输入流,则应当组合使用 FileInputStream 和 BufferedInputStream。...

    编程语言java-io-decorator知识点.pdf

    Decorator模式,也称为Wrapper模式,是设计模式中的一种,它的主要目的是在不修改原有类的基础上,动态地给一个对象添加新的功能。在Java的IO体系中,Decorator模式被广泛应用于输入输出流的组合,以实现不同的功能...

    10、JavaSE:IO流.pdf

    在使用流进行I/O操作时,可以对流进行嵌套组合使用,例如使用装饰器模式(Decorator Pattern),为原始流添加额外的功能,如缓冲、数据转换等。 总之,Java I/O流为数据的输入输出提供了一套强大的工具,使得数据...

    JAVA设计模式在JDK中的应用

    ### JAVA设计模式在JDK中的应用 #### 一、引言 在软件开发过程中,设计模式作为一套被广泛接受的解决方案,能够帮助开发者解决常见的设计问题。Java作为一门流行的编程语言,其标准库(JDK)中巧妙地融入了多种设计...

    装饰者模式——Decorator

    装饰者模式(Decorator)是一种设计模式,用于在运行时动态地给对象添加额外的责任或功能。它是结构型设计模式的一种,能将行为的增加与对象的创建分离,使得我们可以独立地扩展对象的功能。 在Java或其他面向对象...

    JAVA设计模式

    **JAVA设计模式** 在软件工程领域,设计模式是一种在特定情境下解决问题的可复用解决方案。它们是经验的总结,代表了在特定上下文中被广泛接受的、经过时间考验的最佳实践。Java设计模式是面向对象编程中的一种重要...

    java.io包详细解说

    Decorator模式是一种设计模式,它允许我们在运行时向对象添加新的行为或责任,而无需修改该对象的源代码。在Java IO中,Decorator模式主要体现在各种InputStream、OutputStream、Reader和Writer类的使用上。例如,当...

    Java 设计模式最佳实践

    Java 设计模式最佳实践是软件开发中的重要主题,它涵盖了多种模式,这些模式已被广泛接受并应用于实际项目中,以解决常见的编程问题和提升代码的可读性、可维护性和可扩展性。在这个主题中,我们将深入探讨一些关键...

    java_IO完全总结

    Java IO完全总结的知识点: 一、历史背景: ...文章通过介绍Java IO的历史背景、分类、设计模式和特点,以及通过示例和源代码分析的方式,帮助读者深入理解Java IO系统,从而能够更加熟练地运用Java IO进行编程。

    java_io详解

    Java的IO模型采用了装饰者模式(Decorator Pattern),这使得开发者可以根据具体需求动态地组合不同的流类来构建所需的IO功能。例如,如果需要一个具有缓冲功能的文件输入流,可以通过组合`FileInputStream`和`...

    Java_在终极设计模式包中掌握经典设计模式和实际示例.zip

    装饰器模式(Decorator Pattern)是一种结构型设计模式,用于在运行时为对象添加新的行为或职责,而无需修改其原有代码。Java的IO流系统就是装饰器模式的一个经典应用。 代理模式(Proxy Pattern)同样属于结构型...

    JDK中的23个设计模式简介

    JDK 中的 23 个设计模式简介 在 Java 开发领域,设计模式是一个非常重要的概念,它能够帮助开发者写出更加灵活、可维护、可扩展的代码。JDK 中也提供了许多设计模式的实现,本文将对其中的 23 个经典设计模式进行...

Global site tag (gtag.js) - Google Analytics