美高梅网址注册-澳门mgm4858集团登录网址
做最好的网站
来自 澳门mgm4858集团登录网址 2019-10-06 06:02 的文章
当前位置: 美高梅网址注册 > 澳门mgm4858集团登录网址 > 正文

最后附上一篇结合装饰者模式,一般我们为了扩

  • 装饰者和被装饰者有相同的父类
  • 你可以用一个或多个装饰者装饰一个对象。
  • 既然装饰者和被装饰者有相同的父类,所以在任何需要原始对象的场合,可以用装饰过的对象代替它。
  • 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的
  • 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者装饰对象

Java中的IO是明显的装饰器模式的运用。FilterInputStream,FilterOutputStream,FilterRead,FilterWriter分别为具体装饰器的父类,相当于Decorator类,它们分别实现了InputStream,OutputStream,Reader,Writer类(这些类相当于Component,是其他组件类的父类,也是Decorator类的父类)。继承自InputStream,OutputStream,Reader,Writer这四个类的其他类是具体的组件类,每个都有相应的功能,相当于ConcreteComponent类。而继承自FilterInputStream,FilterOutputStream,FilterRead,FilterWriter这四个类的其他类就是具体的装饰器对象类,即ConcreteDecorator类。通过这些装饰器类,可以给我们提供更加具体的有用的功能。如FileInputStream是InputStream的一个子类,从文件中读取数据流,BufferedInputStream是继承自FilterInputStream的具体的装饰器类,该类提供一个内存的缓冲区类保存输入流中的数据。我们使用如下的代码来使用BufferedInputStream装饰FileInputStream,就可以提供一个内存缓冲区来保存从文件中读取的输入流。

其中,FilterInputStream就是装饰模式中的Decorator基类。继承自它的都是装饰器类,它们为输入扩展了功能。

InputStream

/** * This abstract class is the superclass of all classes representing * an input stream of bytes. * * <p> Applications that need to define a subclass of <code>InputStream</code> * must always provide a method that returns the next byte of input.public abstract class InputStream implements Closeable { ...}

InputStream 是所有字节输入流的父类,继承InputStream的子类都要实现返回下一个输入字节的方法.

 具体例子:

由于输入源的读入操作因输入源而异,因此,InputStream中的read()方法是抽象的,由具体的输入源子类实现。

  • 装饰者模式动态的将功能加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

目的:动态地给一个对象添加一些额外的职责。一般我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。在不想增加很多子类的情况下扩展类。将具体功能职责划分,同时继承装饰者模式。

 

四、参考资料

FileInputStream

/** * A <code>FileInputStream</code> obtains input bytes * from a file in a file system. What files * are available depends on the host environment. * * <p><code>FileInputStream</code> is meant for reading streams of raw bytes * such as image data. For reading streams of characters, consider using * <code>FileReader</code>.public class FileInputStream extends InputStream { ...}

FileInputStream主要功能是从文件中读入字节

 

如果不明白装饰模式的话,Java IO 会变的难以理解。而如果不清楚 Java IO 的结构的话,又会觉得它难以使用。这篇博客结合装饰模式介绍了 Java IO 的结构,以及部分 IO 类的实现。这其实是我的学习笔记,如有不足,欢迎指出。

BufferedInputStream

/** * A <code>BufferedInputStream</code> adds * functionality to another input stream-namely, * the ability to buffer the input and to * support the <code>mark</code> and <code>reset</code> * methods. When the <code>BufferedInputStream</code> * is created, an internal buffer array is * created. As bytes from the stream are read * or skipped, the internal buffer is refilled * as necessary from the contained input stream, * many bytes at a time. The <code>mark</code> * operation remembers a point in the input * stream and the <code>reset</code> operation * causes all the bytes read since the most * recent <code>mark</code> operation to be * reread before new bytes are taken from * the contained input stream. */publicclass BufferedInputStream extends FilterInputStream { ...}

BufferedInputStream给InputStream增加一个功能:利用缓存高效读入字节,支持标记和重置。

  • FileInputStream是InputStream的子类,继承之后针对文件读取添加功能,BufferedInputStream是FilterInputStream的子类,FilterInputStream继承了InputStream,所以BufferedInputStream同样是InputStream的子类,构造方法中需要传入一个InputStream。所以如何高效的读入文件就是这样了
public class IOTest { public static void main(String[] args) { File file = new File("test.txt"); try { BufferedInputStream bi = new BufferedInputStream(new FileInputStream; } catch (FileNotFoundException e) { e.printStackTrace(); } }}
  • 创建出来的FileInputStream作为被包装者传给BufferedInputStream,FileInputStream只负责读入文件,当想要提高效率的时候并没有在FileInputStream内部添加缓冲的方法,而是将起作为被装饰者传给BufferedInputStream,BufferedInputStream负责添加高效读入的功能,实现高效率读入文件.单一原则、开闭原则(对扩展开放,对修改关闭)体现的淋漓尽致!

仔细品味装饰者模式的要点,结合Java的IO操作就可以很好的理解装饰者模式了,最后附上一篇结合装饰者模式 优雅的为RecyclerView添加Header以及Footer的博文,加深理解。

图片 1

就像缓冲一样,我们通常会给输入输出加上一些额外的功能。于是问题来了,我们怎么才能让每种输入源都具备这些功能呢?最简单的,就是为每一种输入源的每种额外功能都写一个类,就像下面这样(为了让图小一点,省略了其他的输入源)。

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); //其中file为某个具体文件的File或者FileDescription对象 

后记:对于大部分转行的人来说,找机会把自己的基础知识补齐,边工作边补基础知识,真心很重要。

 (1)组件对象的接口,可以给这些对象动态的添加职责
public abstract class Component {  
    /** 
     * 示例方法 
     */  
    public abstract void operation();  
}  
   (2)具体实现组件对象接口的对象
public class ConcreteComponent extends Component {  

    public void operation() {  
        //相应的功能处理  
    }  

}  
    (3)装饰器接口,维持一个指向组件对象的接口对象, 并定义一个与组件接口一致的接口
public abstract class Decorator extends Component {  
    /** 
     * 持有组件对象 
     */  
    protected Component component;  

    /** 
     * 构造方法,传入组件对象 
     * @param component 组件对象 
     */  
    public Decorator(Component component) {  
        this.component = component;  
    }  

    public void operation() {  
        //转发请求给组件对象,可以在转发前后执行一些附加动作  
        component.operation();  
    }  


}  
    (4)装饰器的具体实现对象,向组件对象添加职责,operationFirst(),operationLast()为前后需要添加的功能。具体的装饰器类ConcreteDecoratorB代码相似,不在给出。
public class ConcreteDecoratorA extends Decorator {  
       public ConcreteDecoratorA(Component component) {  
            super(component);  
   }  
       private void operationFirst(){ } //在调用父类的operation方法之前需要执行的操作  
       private void operationLast(){ } //在调用父类的operation方法之后需要执行的操作  
       public void operation() {  
           //调用父类的方法,可以在调用前后执行一些附加动作  
           operationFirst(); //添加的功能  
           super.operation();  //这里可以选择性的调用父类的方法,如果不调用则相当于完全改写了方法,实现了新的功能  
           operationLast(); //添加的功能  
   }  
}  
    (5) 客户端使用装饰器的代码
public class Client{  
   public static void main(String[] args){  
    Component c1 = new ConcreteComponent (); //首先创建需要被装饰的原始对象(即要被装饰的对象)  
    Decorator decoratorA = new ConcreteDecoratorA(c1); //给对象透明的增加功能A并调用  
    decoratorA .operation();  
    Decorator decoratorB = new ConcreteDecoratorB(c1); //给对象透明的增加功能B并调用  
    decoratorB .operation();  
    Decorator decoratorBandA = new ConcreteDecoratorB(decoratorA);//装饰器也可以装饰具体的装饰对象,此时相当于给对象在增加A的功能基础上在添加功能B  
    decoratorBandA.operation();  
  }  
}  
  1. 缓冲

  (1)需要在不影响其他对象的情况下,以动态、透明的方式给对象添加职责。

其次,重复代码太多。其实同一个功能的代码都差不多,但要给每个输入源都写一遍。写的时候麻烦,到时候要改这个功能的代码,还得一个个改过去,不利于维护。

经典例子:

a = in.read();

 使用场景:

装饰器模式的通用类图

  (2)如果不适合使用子类来进行扩展的时候,可以考虑使用装饰器模式。

Java IO的结构

 

图片 2

装饰模式的扩展性很好。当要为基础类扩展新的功能时,用纯继承语法需要为每种基础类,为另外的各种功能组合编写类。但使用装饰器模式的话,只需要编写一个装饰器类即可。

在我们之前的叙述中,是没有中间这个Decorator抽象类的。它是所有装饰器类的父类,它一方面可以使类的结构更加清晰,另一方面这个抽象类可以减少各个子类中重复逻辑的书写。当然,我们刚才所叙述的也是装饰模式,只不过没有了Decorator抽象类,所有的装饰器类都是直接继承自Component的。这是一种简化的装饰模式。当装饰器数量比较少时,可以省略装饰器基类。另外在确定只有一种Component时,可以不写Component基类,用那一个ConcreteComponent来代替Component基类。

每天都在分享文章,也每天都有人想要我出来给大家分享下怎么去学习Java。大家都知道,我们是学Java全栈的,大家就肯定以为我有全套的Java系统教程。没错,我是有Java全套系统教程,进扣裙974所示,今天小编就免费送!~

我们以输入为例,讲解 Java IO 的结构。输入的基本功能是将数据从某个输入源中读取出来。这个输入源可能是文件,也有可能是一个ByteArray对象,也有可能是一个String对象。数据源不同,读入的方式也不同。因此,Java 的开发者为每种输入源编写了相应的输入类,有从文件中读入数据的FileInputStream,有从ByteArray对象中读入数据的ByteArrayInputStream,……。为了统一接口,减少重复代码的编写,Java 的设计者从这些输入类中,抽取出了相同的部分,编写了抽象输入类InputStream,作为所有输入类的基类。到目前为止,类图可以整理如下,为了方便叙述,省略了一些方法和成员变量。

《Thinking in Java》

Func1Decorator(InputStream in){

Java 的 IO 系统采用了装饰器设计模式。其 IO 分为面向字节和面向字符两种,面向字节以字节为输入输出单位,面向字符以字符为输入输出单位。此外,在每部分中,又分为输入和输出两部分,相互对应,如InputStream类型和OutputStream类型。再往下分,又分为数据源类型和装饰器类型。数据源类型表示的是数据的来源和去处,而装饰器类型可以给输入输出赋予额外的功能。

new BufferedInputStream(new FileInputStream("filename")));

在功能类初始化时,就从外界传入了输入源对象,其后,从数据源读取数据的操作都由这个对象负责,而功能类仅负责对读入的数据进行处理来完成其功能。

其实,之前我们所说的功能类就是装饰器,用来给基础类扩展功能。而这种用组合语法利用多态为基础类扩展功能的模式就是装饰模式。

本文由美高梅网址注册发布于澳门mgm4858集团登录网址,转载请注明出处:最后附上一篇结合装饰者模式,一般我们为了扩

关键词: