装饰器的引入:
BufferedReader 对FileReader拓展了一个功能, readLine.
*** 需求1 :***编写一个类对BufferedReader的功能进行增强, 增强其readLine方法,返回数据带有行号。
*** 需求2 :***编写一个类对BufferedReader的功能进行增强, 增强其readLine方法,返回数据带有分号。
package com.wxhl.jq0803;
import java.io.*;
//带行号的缓冲类。
class BufferedLineNum extends BufferedReader {
int count = 1;
public BufferedLineNum(Reader in) {
super(in); // 该句话只是为了让编译器编译不报错而已。
}
@Override
public String readLine() throws IOException {
String line = super.readLine(); // 调用其父类的readLine方法, null
if (line == null) {
return null;
}
line = count + ":" + line;
count++;
return line;
}
}
// 带有冒号的缓冲类
class BufferedSemi extends BufferedReader {
public BufferedSemi(Reader in) {
super(in);
}
@Override
public String readLine() throws IOException {
String line = super.readLine();
if (line == null) {
return null;
}
line = line + ":";
return line;
}
}
// 带有行号+分号的缓冲类
class LineNumAndSemi extends BufferedLineNum {
public LineNumAndSemi(Reader in) {
super(in);
}
@Override
public String readLine() throws IOException {
String line = super.readLine();
if (line == null) {
return null;
}
line = line + ";";
return line;
}
}
class Demo01 {
public static void main(String[] args) throws IOException {
File file = new File(System.getProperty("user.home")+"/Desktop/user.txt");
FileReader fileReader = new FileReader (file);
LineNumAndSemi lineSemi = new LineNumAndSemi(fileReader);
String line = null;
while((line = lineSemi.readLine())!=null){
System.out.println(line);
}
lineSemi.close();
}
}
分析:
从上可知,想拓展readLine()方法,返回带有行号的数据时,BufferedLineNum类需要继承自BufferedReader类,且重写readLine()方法,然后在父类的readLine()基础上拓展出"有行号"功能
当又想拓展"有行号"功能,加上"有分号"功能时,LineNumAndSemi类又需要继承自BufferedLineNum类,再在其父类readLine()功能基础上进行拓展
这样,如果再需要拓展出其他功能,又需要继承自LineNumAndSemi类,是不是好一个庞大的继承体系呀,好臃肿有没有
改进(装饰者设计模式):
import java.io.*;
//返回带有行号的缓冲类
class BufferedLineNum2 extends BufferedReader{
BufferedReader bufferedReader; // BufferedReader bufferedReader = new BufferedSemi();
int count = 1;
public BufferedLineNum2(BufferedReader bufferedReader){ // BufferedReader bufferedReader = new BufferedSemi();
super(bufferedReader);
this.bufferedReader = bufferedReader;
}
public String readLine() throws IOException {
String line = bufferedReader.readLine(); // 解决方案:如果这里的readLine方法是BufferedSemi的readline方法那么该问题解决了。
if(line==null){
return null;
}
line = count+":"+line;
count++;
return line;
}
}
//返回带有很好的缓冲类
class BufferedSemi2 extends BufferedReader{
BufferedReader bufferedReader; // BufferedReader bufferedReader = new BufferedSemi();
public BufferedSemi2(BufferedReader bufferedReader){ // BufferedReader bufferedReader = new BufferedSemi();
super(bufferedReader);
this.bufferedReader = bufferedReader;
}
public String readLine() throws IOException {
String line = bufferedReader.readLine(); // 解决方案:如果这里的readLine方法是BufferedSemi的readline方法那么该问题解决了。
if(line==null){
return null;
}
line = line+";";
return line;
}
}
public class Demo02{
public static void main(String[] args) throws IOException {
File file = new File(System.getProperty("user.home")+"/Desktop/user.txt");
FileReader fileReader = new FileReader (file);
BufferedReader bufReader = new BufferedReader(fileReader);
LineNumAndSemi lineSemi = new LineNumAndSemi(bufReader);
String line = null;
while((line = lineSemi.readLine())!=null){
System.out.println(line);
}
lineSemi.close();
}
}
从上可以看出,虽然只是实现了相同的功能,但是装饰者模式明显搭配灵活,需要用到哪个类的拓展功能,直接传入其对象即可
而且还避免了不断继承的臃肿
另外的模拟
package cn.itcast.add;
/*
需求: 一家三口都要工作, 儿子工作负责绘画, 妈妈可以在儿子的工作上进行增强---》上涂料, 爸爸的工作就是在妈妈的基础上增强--->上画框
*/
interface Work{
public void work();
}
class Son implements Work{
@Override
public void work() {
System.out.println("在画画...");
}
}
class Mother implements Work{
//在内部维护一个 需要被增强的类
Work w; // work w = new Son();
public Mother(Work w){
this.w = w;
}
@Override
public void work() {
w.work();
System.out.println("妈妈上涂料...");
}
}
//
class Father implements Work{
Work w;
public Father(Work w){
this.w = w;
}
@Override
public void work() {
w.work();
System.out.println("爸爸上画框...");
}
}
public class Demo3 {
public static void main(String[] args) {
Son s = new Son();
Mother m = new Mother(s);
Father father = new Father(m);
father.work();
}
}