在添加 不同功能的时候。我们会想到了用继承来实现。而且刚学装饰者模式的时候,觉得挺难理解的,装饰者的前世今生就是继承。那为什么不用继承呢?这样岂不是更容易理解,用起来也挺方便。下面通过一个简单的Demo做一下比较。
需求:用继承来实现通过readLine读取代码 ,每一行加上一个行号和分号的功能
//1.添加行号,默认继承BufferedReader
class BufferedReaderLineNum extends BufferedReader {
int count = 0;
public BufferedReaderLineNum(BufferedReader in) { //Reader:默认创建一个目标文件的缓冲字符输入流的大小
super(in);
}
@Override//3.重写父类的readLine方法
public String readLine() throws IOException {
String countent = super.readLine();//调用父类默认的行号
if (countent == null) {
return null;
}
//System.out.println(count + " " + countent);
count++;
return count + " " + countent;
}
}
//添加分号
class BufferedReaderSemicolon extends BufferedReader {
BufferedReader reader;
public BufferedReaderSemicolon(BufferedReader in) {//Reader:默认创建一个目标文件的缓冲字符输入流的大小
super(in);
this.reader = in;
}
@Override//3.重写父类的readLine方法
public String readLine() throws IOException {
String countent = reader.readLine();
if (countent == null) { //判断数据已经读完
return null;
}
return countent + ";";
}
}
public class Demo1 {
public static void main(String[] args) throws IOException {
//FileReader用于字符输入流,FileInputStream是用字节输入流
//1.创建通道,拿到一个指定的目标文件
FileReader fileRead = new FileReader("C:\\java\\decorator\\Test.java");
BufferedReader reader = new BufferedReader(fileRead);
//2.创建行号的缓冲流
BufferedReaderLineNum readerLineNum = new BufferedReaderLineNum(reader);
//.创建分号的缓冲流
BufferedReaderSemicolon readerSemicolon = new BufferedReaderSemicolon(readerLineNum);
String content = null;
//使用readLine(),包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
while((content = readerSemicolon.readLine()) != null) {
System.out.println(content);
}
//4.关闭资源
readerLineNum.close();
}
}
然后再通过装饰者模式来实现上面的功能:
//添加行号 class BufferederReadLineNum extends BufferedReader { BufferedReader bufferedReader; //1.内部维护的被装饰者的类 int count = 1; public BufferederReadLineNum(BufferedReader read) { super(read);//如果没有这行代码,会显示编译报错,显示没有隐式性的给这个构造函数定义 this.bufferedReader = read; } @Override public String readLine() throws IOException { String countent = bufferedReader.readLine(); if(countent == null) { return null; } countent = count + " " + countent; count++; return countent; } } //2.添加分号 class BufferedReaderSemicolon1 extends BufferedReader { BufferedReader bufferedReader; //1.内部维护的被装饰者的类 public BufferedReaderSemicolon1(BufferedReader read) { super(read); this.bufferedReader = read; } @Override//3.重写父类的readLine方法 public String readLine() throws IOException { String countent = super.readLine(); //调用父类默认的行号 if (countent == null) { //判断数据已经读完 return null; } return countent + ";"; } } public class Test2 { public static void main(String[] args) throws IOException { //1.创建通道,拿到一个指定的目标文件 FileReader fileRead = new FileReader("C:\\java\\代码\\src\\Test.java"); //2.创建缓冲区 BufferedReader bufferedReader = new BufferedReader(fileRead); //3创建分号的缓冲流 BufferedReaderSemicolon1 readerSemicolon = new BufferedReaderSemicolon1(bufferedReader); //创建行号的缓冲流 在装饰者创建的 BufferederReadLineNum readerLineNum = new BufferederReadLineNum(readerSemicolon); //4.读取数据 String content = null; //使用readLine(),包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null while((content = readerLineNum.readLine()) != null) { System.out.println(content); } //5.关闭资源 readerLineNum.close(); } }
通过上面的代码,可能不能完全看出使用装饰者模式的强大功能,你可以在多创建几个类,添加多个功能,结果就显而易见了。
在实现多个功能的时候,使用继承的体系会过于庞大,显得很臃肿。