前言

Java里面的I/O这一部分看过很多遍,每次看完之后特别混乱,又是输入流,又是输出流,又是字符流,又是字节流,还有什么过滤流,缓冲流。每次看得我如入云里雾里,直到后面看了设计模式这一块,才算真正的对Java I/O这一块有了整体的了解,理解起Java流也就容易许多。这篇博客先介绍装饰者模式,然后结合Java流看看装饰者模式如何应用到Java流中的。

装饰者模式

装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。在如下三种情况下可以选择使用装饰者模式。

  • 1)需要扩展一个类的功能,或给一个类增加附加责任。
  • 2)需要动态的给一个对象增加功能,这些功能可以再动态地撤销。
  • 3)需要增加一些基本功能的排列组合而产生的非常大量的功能,从而使继承变得 不现实。

装饰者角色结构如下图所示:

由上图可知在装饰者模式中一共有两个角色,一个是被装饰者,一个是装饰者。装饰者类和被装饰者类有共同的超类。在具体装饰者类上面还有一个抽象装饰者类。抽象装饰者类的主要功能是强制具体装饰者类实现对被装饰者类增加的功能。装饰者的类图如下:

装饰者模式实例
现在有一杯白开水(WaterClass),想向白开水里面加茶叶(TeaClass),加点糖(SugarClass),或者加点盐(SaltClass)。也许会认为那还不简单吗,加茶叶的白开水就再生成一个(WaterWithTeaClass),加糖的白开水就再生成一个(WaterWithSugarClass)这样不就行了吗?但是如果我们既要加糖又要加茶叶,或者加盐加糖这样的组合会很多,可能就要生成很多的类,造成类泛滥。这时候就要用到装饰者模式了。下面看看装饰者模式是如何轻松解决这个问题的。

WaterComponent:(被装饰者)

public class WaterComponent implements DrinkComponent{@Overridepublic void operation() {// TODO Auto-generated method stubSystem.out.print("water drink");}}

SugarDecorator:(装饰者)

public class SugarDecorator extends DrinkDecorator{public SugarDecorator(DrinkComponent component) {super(component);// TODO Auto-generated constructor stub}public void operation(){component.operation();System.out.print(",with sugar");}
}

TeaDecorator:(装饰者)

public class TeaDecorator extends DrinkDecorator{public TeaDecorator(DrinkComponent component) {super(component);// TODO Auto-generated constructor stub}public void operation(){component.operation();System.out.print(",with Tea");}
}

MainClass

public class MainClass {public static void main(String[] args) {// TODO Auto-generated method stubWaterComponent water=new WaterComponent();SugarDecorator sugar=new SugarDecorator(water);
//往白开水里面加糖。TeaDecorator tea=new TeaDecorator(sugar);
//往加糖的白开水里面加茶叶。tea.operation();/*一杯有茶叶和糖的白开水就这样产生了,你也可以自由的往白开水里面加自己喜欢的东西,而并不造成类泛滥只需要继承DrinkDecorator就行*/}}

由这个实例应该对装饰者模式有了了解,下面就来看看装饰者模式是如何应用到Java I/O中来的。

装饰者模式与Java I/O

先用一幅图来看看Java I/O到底是什么。下面的这幅图生动的刻画了Java I/O的作用。

由上图可知在Java中应用程序通过输入流(InputStream)的Read方法从源地址处读取字节,然后通过输出流(OutputStream)的Write方法将流写入到目的地址。流的来源主要有三种:

  • ①本地的文件(File)
  • ②控制台
  • ③通过socket实现的网络通信

下面的图可以看出Java中的装饰者类和被装饰者类以及它们之间的关系,这里只列出了InputStream中的关系。

由上图可以看出只要继承了FilterInputStream的类就是装饰者类,可以用于包装其他的流,装饰者类还可以对装饰者和类进行再包装。下面看一下Java中包装流的实例:

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class StreamDemo {public static void main(String[] args) throws IOException{DataInputStream in=new DataInputStream(new BufferedInputStream(new  FileInputStream("D:\\JAVAworkspace\\ProgramTest\\src\\StreamDemo.java")));while(in.available()!=0){System.out.print((char)in.readByte());}in.close();}}

上面程序中对流进行了两次包装,先用 BufferedInputStream将FileInputStream包装成缓冲流也就是给FileInputStream增加缓冲功能,再DataInputStream进一步包装方便数据处理。

实现自己的包装流

了解了装饰者模式以及在Java中的应用,下面就来实现一个自己的包装流,要实现装饰者类,按照上面的图必须先得实现FilterInputStream装饰者抽象类。来实现这样一个操作的装饰者类:将输入流中的所有小写字母变成大写字母。

import java.io.FileInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;public class UpperCaseInputStream extends FilterInputStream {protected UpperCaseInputStream(InputStream in) {super(in);}@Overridepublic int read() throws IOException {int c=super.read();return (c==-1?c:Character.toUpperCase(c));}@Overridepublic int read(byte[] b, int off, int len) throws IOException {int result=super.read(b, off, len);for(int i=off;i<off+result;i++){b[i]=(byte)Character.toUpperCase((char)b[i]);}return  result;}public static void main(String[] args) throws IOException {int c;InputStream in=new UpperCaseInputStream(new FileInputStream("D:\\JAVAworkspace\\ProgramTest\\src\\StreamDemo.java"));try {while((c=in.read())>=0){System.out.print((char)c);}} finally{in.close();}}}

输出结果:

IMPORT JAVA.IO.BUFFEREDINPUTSTREAM;
IMPORT JAVA.IO.DATAINPUTSTREAM;
IMPORT JAVA.IO.FILEINPUTSTREAM;
IMPORT JAVA.IO.IOEXCEPTION;
PUBLIC CLASS STREAMDEMO {PUBLIC STATIC VOID MAIN(STRING[] ARGS) THROWS IOEXCEPTION{DATAINPUTSTREAM IN=NEW DATAINPUTSTREAM(NEW BUFFEREDINPUTSTREAM(NEW FILEINPUTSTREAM("D:\\JAVAWORKSPACE\\PROGRAMTEST\\SRC\\STREAMDEMO.JAVA")));WHILE(IN.AVAILABLE()!=0){SYSTEM.OUT.PRINT((CHAR)IN.READBYTE());}IN.CLOSE();}}

参考文献

1.java编程思想(Thinking In Java) 
2.Head First 设计模式 
3.https://www.javatpoint.com/java-io

原文:https://blog.csdn.net/u013309870/article/details/75735676

转载于:https://www.cnblogs.com/Terry-Wu/p/10111093.html

由装饰者模式来深入理解Java I/O整体框架相关推荐

  1. python装饰器模式带参数_python 装饰器模式 我的理解

    python和javascript类似, 可以把函数当作函数的返回值, 比如 def func(f): def subfunc(): print 'subfunc' return subfunc此外f ...

  2. java中的工厂模式_深入理解Java的三种工厂模式

    一.简单工厂模式 简单工厂的定义:提供一个创建对象实例的功能,而无须关心其具体实现.被创建实例的类型可以是接口.抽象类,也可以是具体的类 实现汽车接口 奔驰类 宝马类 简单工厂,既能生产宝马又能生产奔 ...

  3. java bean 工厂模式_深入理解Java的三种工厂模式

    一.简单工厂模式 简单工厂的定义:提供一个创建对象实例的功能,而无须关心其具体实现.被创建实例的类型可以是接口.抽象类,也可以是具体的类 实现汽车接口 public interfaceCar { St ...

  4. java中三个基本框架_对于Java基础者应该如何理解Java中的三大框架!

    三大框架:Struts+Hibernate+Spring Java三大框架主要用来做WEN应用. Struts主要负责表示层的显示 Spring利用它的IOC和AOP来处理控制业务(负责对数据库的操作 ...

  5. java 等待线程结束 框架_深入理解Java多线程与并发框架——线程的状态

    欢迎关注专栏<Java架构筑基>--专注于Java技术的研究与分享!Java架构筑基​zhuanlan.zhihu.comJava架构筑基--专注于Java技术的研究与分享! 后续文章将首 ...

  6. java 线程 原子性_深入理解Java多线程与并发框架——Java内存模型与原子性、可见性、有序性...

    欢迎关注专栏<Java架构筑基>--专注于Java技术的研究与分享!Java架构筑基​zhuanlan.zhihu.comJava架构筑基--专注于Java技术的研究与分享! 后续文章将首 ...

  7. Java/Android 设计模式系列(7)--装饰者模式

    这篇将会介绍装饰者模式(Decorator Pattern),装饰者模式也称为包装模式(Wrapper Pattern),结构型模式之一,其使用一种对客户端透明的方式来动态的扩展对象的功能,同时它也是 ...

  8. java/android 设计模式学习笔记(7)---装饰者模式

    这篇将会介绍装饰者模式(Decorator Pattern),装饰者模式也称为包装模式(Wrapper Pattern),结构型模式之一,其使用一种对客户端透明的方式来动态的扩展对象的功能,同时它也是 ...

  9. java装饰者模式讲解视频教程_java装饰者模式介绍(图文教程)

    java装饰者模式介绍(图文教程).装饰者模式UML类图: 装饰者模式UML类图 java装饰者模式知识要点 装饰者模式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. ...

  10. java中的装饰者模式[63]

    java中的装饰者模式[63] 文章目录 java中的装饰者模式[63] 一.什么是装饰者模式? 二.装饰者模式要点 三.代码演示 四.小结 一.什么是装饰者模式? **1.意图:**动态的给一个对象 ...

最新文章

  1. android时间utc,Android获取UTC时间的方式
  2. 细胞因子风暴与新冠肺炎
  3. python基础练习(九)
  4. 如何在 Windows XP 的事件查看器中查看和管理事件日志
  5. oracle取本月最后一天是星期几_Oracle取得本月、本年第一天和最后一天
  6. Java servlet项目里的web.xml
  7. python工程师面试宝典_2019年,Python工程师必考的6个面试题,Python面试题No5
  8. 放弃高考“打游戏”,别人25岁年入百万、我退役后回家修车
  9. clion 32位xp安装 64位软件
  10. [zz]Win8应用商店管理小工具
  11. NAT映射和代理服务器
  12. Android应用市场和应用包名大全
  13. java查询图片前台展示_Java +spring MVC 后台图片流在前台页面显示
  14. 红尘阡陌,那抹温暖的烟火
  15. decelerate(decelerates)
  16. uniapp获取微信头像和昵称
  17. 16天记住7000考研单词(第一天)
  18. 内积到底是什么?和卷积的联系是什么
  19. 【移动端聊天功能模板】Vue实现H5聊天系统,实现上下固定中间滚动布局,微信授权功能,自动滚动到底部【详细注释,一看就会】
  20. C++ 程序编译过程:从代码到程序

热门文章

  1. PHP扩展部署之最佳实践
  2. STL—内存的配置与释放
  3. 脑力劳动者,如何休息使自己精力充沛
  4. Oracle 宣布 Java EE 8 推迟到2017年年底发布
  5. requireJS多页面应用实例
  6. LVS基本介绍及NAT模型配置示例
  7. mac下直接下载xcode的地址
  8. windows下mysql-8.0.11的安装
  9. linux主从库配置文件,Linux系统中MongoDB安装及主从配置linux操作系统 -电脑资料
  10. wxpython和tkinter哪个好_为什么很多Python开发者写GUI不用Tkinter,而要选择PyQt和wxPython或其他?...