• 黑马程序员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 ,直接抛出异常。

  • 相关阅读:
    书单
    部署邮件系统
    解决配置文件注释太多的方法
    SHELL脚本自动备份
    如何在 Centos7 中修改yum源(三种方法)
    关于油猴子脚本的下载和使用方法
    问卷星全自动刷流量
    实验四、EIGRP 高级实验
    CentOS7修改主机名的三种方法
    IntelliJ IDEA 2018.3 x64的破解和安装
  • 原文地址:https://www.cnblogs.com/jbelial/p/3059917.html
Copyright © 2020-2023  润新知