`
bingzhen66
  • 浏览: 37025 次
文章分类
社区版块
存档分类
最新评论

47.黑马程序员-IO流缓冲区、装饰设计模式

 
阅读更多

------- android培训java培训、期待与您交流! ----------

一、缓冲区
  • 概念:缓冲区的出现提高了对数据的读写效率。
  • 对应类:BufferedWriter、BufferReader。
  • 缓冲区要结合流才可以使用。缓冲区对流进行了增强。
1.BufferedWriter缓冲区
  • 打开缓冲区:只需要将流对象最为参数传递给构造函数即可。
    • BufferedWriter bufw = new BufferedWriter (fw) //fw为FileWriter对象。
  • 使用缓冲区:因为缓冲区也继承自Writer,可以使用Writer的方法。
    • 写入需要使用write(“内容”)
    • newLine(); //换行,在linux,windows等OS下都是换行,提高通用性。
      • //返回的时候只返回回车符之前的数据内容,并不返回回车符。所以注意:每次line =redaLine()读取完,write(line)后,必须加上两句:bufw.newLine();和bufw.flush(); 。否则写到文件中的数据没有换行符。
    • 使用缓冲区记得刷新flush()。
  • 关闭缓冲区: 直接关闭bufw即可。流对象才是具体操作数据的。关闭缓冲区其实就是关闭缓冲区中的流对象。
    • bufw.close();
2.BufferedReader缓冲区
  • 打开缓冲区:只需要将流对象最为参数传递给构造函数即可。
    • BufferedReader bufr = newBuffered Reader(fr) //fr为FileWriter对象。
  • 使用缓冲区:因为缓冲区也继承自Writer,可以使用Writer的方法。使用缓冲区记得刷新
    • 读取方法redaLine();
      • //读一行。返回值类型string,为null就读完。
      • //返回的时候只返回回车符之前的数据内容,并不返回回车符。所以注意:每次line =redaLine()读取完,write(line)后,必须加上两句:bufw.newLine();和bufw.flush(); 。 否则写到文件中的数据没有换行符。
      • 原理:
      • 1.无论是读一行,还是获取多个字符,最终都是在硬盘上一个一个读取。
      • 2.读取到的字符存在一个数组中,当读取到\r时就先不存而是继续读取, 下一个是\n时就代表一行结束,返回这个数组。注意\r\n不会返回。
    • 读取不需要刷新。
  • 关闭缓冲区:直接关闭bufw即可。流对象才是具体操作数据的。关闭缓冲区其实就是关闭缓冲区中的流对象。
    • burw.close();
3.通过缓冲区复制文件。
  • 复制一个.java文件。
    • /*
      通过缓冲区复制一个.java文件
      */
      import java.io.*;
      class  CopyTextByBuf
      {
      	public static void main(String[] args) 
      	{
      		BufferedReader bufr = null;
      		BufferedWriter bufw = null;
      		try
      		{
      			bufr = new BufferedReader(new FileReader("c:\\buf.txt"));
      			bufw = new BufferedWriter(new FileWriter("d:\\Copy_buf.txt"));
      			String line = null;
      			while ((line = bufr.readLine())!=null)
      			{
      				bufw.write(line);
      				bufw.flush();
      			}
      		}
      		catch (IOException e)
      		{
      			throw new RuntimeException("读写失败");
      		}
      		finally
      		{
      			try
      			{
      				if (bufr != null)
      				{
      					bufr.close();
      				}
      			}
      				
      			catch (IOException e)
      			{
      				throw new RuntimeException("读取关闭失败");
      			}
      
      			try
      			{
      				if (bufw != null)
      				{
      					bufr.close();
      				}
      			}
      				
      			catch (IOException e)
      			{
      				throw new RuntimeException("写入关闭失败");
      			}
      		}
      	}
      }
      

二、装饰设计模式
1.概念
  • 当想要对已有对象进行功能增强时,可以定义类,将已有对象传入,给予已有的功能,并提供加强功能,那么自定义的类成为装饰类。
  • BufferedReader就属于装饰类。
2.举例
  • MyReader //专门用于读取数据的类
    • |--MyTextReader
      • |--MyBufferTextReader
    • |--MyMediaReader
      • |--MyMediaTextReader
    • |--MyDataReader
      • |--MyDataTextReader
    • 这个类扩展性不好、臃肿。用的缓冲技术是一样的,没必要定义单独的子类,我们可以定义一个缓冲区,谁需要缓冲就传进来。
    • 那么重载构造函数行不行呢?
    • class MyBufferReader
    • {
      • MyBufferReader( MyBufferTextReader){}
      • MyBufferReader( MyMediaTextReader){}
      • MyBufferReader( MyDataTextReader){}
    • }//这个类扩展性也是极差,找到其参数的共同类型,通过多态的形式,可以提高效率。
    • 装饰设计模式:
    • class MyBufferReader extends MyReader
    • {
      • MyBufferReader( MyReader r){}
    • }
    • 装饰模式结构
      • MyReader //专门用于读取数据的类
        • |--MyTextReader
        • |--MyMediaReader
        • |--MyDataReader
        • |--MyBufferReader
3.与继承的区别
  • 装饰模式比继承要灵活,避免了继承体系的臃肿。从而降低了类与类之间的关系。
  • 装饰类因为增强已有的对象,具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常是一个体系中的。
  • 不要已继承为主,可以通过装饰扩展。
  • 当发现一个类的功能不够用,可以新建一个装饰类,把原来的类传入进来。
4.装饰类继承父类
  • 例如继承Reader类,如何覆盖Reader类中的抽象方法。
    • 可以通过Reader类的子类复写,直接返回子类对象的方法就可以。
    • 例如 Reader类的read方法是抽象方法。代码:
    • MyBufferedReader (Reader r){this.r=r;}// MyBufferedReader是装饰类,r是被装饰的Reader类的子类。
    • public int read(char[] buff,int off, int len)
    • {
      • return r.read(buff,off,len);//这里怎么实现不知道,可以使用传进来的子类去实现。
    • }
5.总结
  • 装饰类与“被装饰的多个类”都集成同一个父类,
  • 与它们平行,简化了继承的臃肿。

  • BufferdeReader与BufferdeWriter就是Reader类和Writer类的装饰类。
  • 继承Reader类和Writer类并且需要覆盖一些抽象方法。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics