黑马程序员JAVA基础IO流中的装饰设计模式

装饰设计模式:

  当想要对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,并提供加强功能。那么,自定义的该类称为装饰类。

  装饰类通常会通过构造方法接收被装饰的类,并基于被装饰的对象的功能,提供更强的功能。

  

装饰和继承的区别:

  装饰模式:

  MyReader // 专门用于读取数据的类。

    |--MyTextReader 

    |--MyMediaReader 

    |--MyDataReader 

    |--MyBufferReader // 装饰类:增强MyReader 读取功能。

  此时 MyBufferReader 类如: 

     class MyBufferReader extends MyReader {
         MyBufferReader(MyReader r){
         }
     }

  继承: 

  MyReader // 专门用于读取数据的类。

    |--MyTextReader 

      |--MyBufferTextReader

    |--MyMediaReader 

      |--MyBufferMediaReader

    |--MyDataReader 

      |--MyBufferDataReader 

    class MyBufferReader
     {
         MyBufferReader(MyTextReader text) {}
         MyBufferReader(MyMediaReader media){}
         如果要添加子类。如MyBufferDataReader。则要修改此处的代码。。。
         所以使用继承的话,代码不安全。
     }

  通过如上的比较,可以知道:装饰模式比继承要灵活。避免了继承体系的臃肿,而且降低了类与类之间的关系。

  装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强的功能,所以装饰类和被装饰类通常都属于一个体系中的。

  模拟: BufferedReader 类,并完成其的特用方法 readLine() ;

  > readLine() : 每次读一行数据。

 1 import java.io.*; 
 2 public class MyBufferedReader {
 3     private  FileReader fr = null ;
 4     public MyBufferedReader(FileReader fr) {
 5         this.fr = fr ;
 6     }
 7 //    模拟 readLine 方法,一次读一行
 8     public String MyReadLine() throws IOException{
 9 //        定义一个临时容器
10         StringBuilder sb = new StringBuilder() ;  
11         int ch = 0 ;  
12         while ((ch = fr.read()) != -1) {
13             if (ch == '\r')
14                 continue ; 
15             if (ch == '\n')
16                 return  sb.toString() ; 
17             sb.append((char)ch) ; 
18         }
19         if (sb.length() != 0) 
20             return sb.toString() ;
21         return null ;
22     }
23     public void myClose() throws IOException {
24         fr.close() ;
25     }
26 }

  模拟:BufferedInputStream 类,自定义MyBufferedInputStream 类。

  首先:分析BufferedInputStream 类的原理:1、从硬盘上读取数据到缓冲区(new FileInputStream("....").read(buf) ;) 。

                       2、从缓冲区读取数据。 

 1 import java.io.*; 
 2 public class MyBufferedInputStream {
 3     private InputStream in  ; 
 4     
 5 //    定义容器:
 6     private byte[] buf = new byte[1024] ; 
 7 //    定义计数器:
 8     private int pos = 0 ; 
 9     private int count = 0 ;
10     
11     MyBufferedInputStream(InputStream in ) {
12         this.in = in ; 
13     }
14     
15 //    一次读一个字节,从缓冲区(字节数组)获取。
16     public int MyRead() throws IOException {
17 //        通过in对象读取硬盘上数据,并存储buf中。
18         if(count == 0) {
19             count = in.read(buf) ; 
20             if (count < 0)
21                 return -1 ; 
22             pos = 0 ; 
23             byte b = buf[pos] ; 
24             
25             count -- ; 
26             pos ++ ;
27             return b&255 ; 
28         } 
29         else if (count >0) {
30             byte b = buf[pos] ; 
31             
32             count -- ; 
33             pos ++ ;
34             return b&255 ; 
35         }
36         return -1 ;
37     }
38     public void  MyClose() throws IOException {
39         in.close() ; 
40     }
41 }

  上述代码:buf 用来存储从硬盘中读取的数据;其中返回int 型则是对 byte 数据的提升。 因为b 是byte 型,转换成int 型时,前面会自动补1,而为了避免补1,所以与255相& 。

    在定义功能方法时,不用使用try ,直接抛出异常。

原文地址:https://www.cnblogs.com/jbelial/p/3059917.html