JavaSE笔记15.3-IO流-装饰设计模式
1. 定义
当想要对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,提供增强功能。
那么自定义的该类称为装饰类。
2. 用法
(1)装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰对象的功能,提供更强的功能
(2)装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常都是属于一个体系中的
//被装饰类
class Person{
public void lunch(){
System.out.println("fruit");
}
}
//装饰类
class SuperPerson{
private Person p;
//将已有对象传入
SuperPerson(Person p){
this.p=p;
}
//基于已有的功能,提供增强功能
public void superLunch(){
p.lunch();
System.out.println("dessert");
System.out.println("vegetables");
}
}
public class PersonDemo {
public static void main(String[] args) {
Person p=new Person();
SuperPerson sp=new SuperPerson(p);
sp.superLunch();
}
}
3. 装饰和继承的区别
例子:有一个专门用于读取数据的父类MyReader,根据读取的格式不同扩展了子类MyTextReader、MyMediaReader、MyDataReader,现在要给这3个子类增加缓冲功能
用继承的模式:
MyReader
|--MyTextReader
|--MyBufferedTextReader
|--MyMediaReader
|--MyBufferedMediaReader
|--MyDataReader
|--MyBufferedDataReader
用装饰的模式:
MyReader
|--MyTextReader
|--MyMediaReader
|--MyDataReader
|--MyBufferedReader
class MyBufferedReader extends MyReader{
MyBufferedReader(MyReader r)//利用多态,如MyReader r=new MyTextReader()
}
继承和装饰的区别:
装饰模式比继承继承更灵活,避免了继承体系的臃肿,而且降低了类与类之间的耦合性。
4. 例子
需求:
自定义具有读一行文本功能的装饰类MyBufferedReader,被装饰类是Reader;
基于Reader对象的读单个字符功能read(),提供读一行文本的增强功能myReadLine()
import java.io.*;
//自定义装饰类MyBufferedReader
//装饰类和被装饰类通常属于同一体系,所以继承了Reader
class MyBufferedReader extends Reader{
//装饰模式,通过构造方法接收被装饰的对象
private Reader r;
MyBufferedReader(Reader r){
this.r=r;
}
//自定义一个读取一行文本的方法
public String myReadLine() throws IOException {
//原BufferedReader中的readLine方法封装的是字符数组
//为了演示方便,定义一个临时容器StringBuilder,StringBuilder长度可变并且最终可通过toString方法变成字符串
StringBuilder sb=new StringBuilder();
int ch=0;
while ((ch=r.read())!=-1){
if(ch=='\r')
continue;
//到了行尾,打印该行字符
if(ch=='\n')
return sb.toString();
else
sb.append((char)ch);
}
//已读到文件结尾处,但文件结尾处缺少换行符
if(sb.length()!=0)
return sb.toString();
//已读到文件结尾处,文件结尾处有换行符
return null;
}
//简单覆盖下Reader类中的抽象方法
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
return r.read(cbuf,off,len);
}
@Override
public void close() throws IOException {
r.close();
}
}
//使用装饰类MyBufferedReader
public class MyBufferedReaderDemo {
public static void main(String[] args) {
MyBufferedReader bufr=null;
try{
FileReader fr=new FileReader("buf.txt");
bufr=new MyBufferedReader(fr);
//向缓冲区中读数据
String line=null;
while ((line=bufr.myReadLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
throw new RuntimeException("读写失败");
}
finally {
try{
if(bufr!=null)
bufr.close();
} catch (IOException e) {
throw new RuntimeException("关闭流失败");
}
}
}
}