装饰器模式
需求:想要在读取的文件的每一行添加行号。
public class IoTest7_BufferedReader { public static void main(String[] args) throws IOException { readFile("c:\a.txt"); } private static void readFile(String path) throws IOException { Reader read = new FileReader(path); BufferedReader br = new BufferedReader(read); int count = 0; String line = null; while ((line = br.readLine()) != null) { count++; System.out.println(count+":"+line); } } }
很容易的就可以实现。如果每次使用BufferedReader 输出时都需要显示行号呢? 每次都加? 很显然,我们的BufferedReader继承了Reader 对父类进行了功能的增强,那么我们也可以继承BufferedReader 重写该类的readLine方法,进行功能的增强.
public class IoTest_BufferedReader { public static void main(String[] args) throws IOException { readFile("c:\a.txt"); } private static void readFile(String path) throws IOException { Reader read = new FileReader(path); BufferedReader br = new MyBufferedReader(read); String line = null; while ((line = br.readLine()) != null) { System.out.println(line); } } } class MyBufferedReader extends BufferedReader { public MyBufferedReader(Reader read) { super(read); } int count; @Override public String readLine() throws IOException { String line = super.readLine(); if (line != null) { count++; return count + ":" + line; } else { return null; } } }
需求:
要在输出的一行前加上引号
可以再定义一个BufferedReader的子类,继承BufferedReader增强功能.
public class IoTest_BufferedReader { public static void main(String[] args) throws IOException { readFile("c:\a.txt"); } private static void readFile(String path) throws IOException { Reader read = new FileReader(path); BufferedReader br = new MyQutoBufferedReader(read); int count = 0; String line = null; while ((line = br.readLine()) != null) { System.out.println(line); count++; } } } // quotation 引号 class MyQutoBufferedReader extends BufferedReader { public MyQutoBufferedReader(Reader reader) { super(reader); } public String readLine() throws IOException { String line = super.readLine(); if (line != null) { return """ + line + """; } else { return null; } } }
需求三:
既想要显示行号又想要显示引号
发现,就需要再定义子类,发现这样比较麻烦,代码臃肿.而且代码重复.
可以换一种方式.如下:
其实就是一个新类要对原有类进行功能增强.
1. 在增强类中维护一个被增强的父类引用变量
2. 在增强类的构造函数中初始化1中的变量
3. 创建需要增强的方法,在刚方法中调用被被增强类的方法,并加以增强。
public class IoTest_BufferedReader { public static void main(String[] args) throws IOException { readFile("c:\a.txt"); } private static void readFile(String path) throws IOException { Reader read = new FileReader(path); BufferedReader bufferedReader = new BufferedReader(read); BufferedReader br = new MyQutoBufferedReader2(bufferedReader); br = new MyLineBufferedReader2(br); String line = null; while ((line = br.readLine()) != null) { System.out.println(line); } } } // quotation 引号 class MyQutoBufferedReader2 extends BufferedReader { private BufferedReader bufferedReader; public MyQutoBufferedReader2(BufferedReader bufferedReader) { super(bufferedReader); this.bufferedReader = bufferedReader; } public String readLine() throws IOException { String line = super.readLine(); if (line != null) { return """ + line + """; } else { return null; } } } class MyLineBufferedReader2 extends BufferedReader { private BufferedReader bufferedReader; public MyLineBufferedReader2(BufferedReader bufferedReader) { super(bufferedReader); this.bufferedReader = bufferedReader; } int count; @Override public String readLine() throws IOException { String line = super.readLine(); if (line != null) { count++; return count + ":" + line; } else { return null; } } }
这就是装饰器模式
装饰器模式:
使用分层对象来动态透明的向单个对象中添加责任(功能)。
装饰器指定包装在最初的对象周围的所有对象都具有相同的基本接口。
某些对象是可装饰的,可以通过将其他类包装在这个可装饰对象的四周,来将功能分层。
装饰器必须具有和他所装饰的对象相同的接口。
JavaIO中的应用:
Java I/O类库需要多种不同的功能组合,所以使用了装饰器模式。
FilterXxx类是JavaIO提供的装饰器基类,即我们要想实现一个新的装饰器,就要继承这些类。
装饰器与继承:
问题:
修饰模式做的增强功能按照继承的特点也是可以实现的,为什么还要提出修饰设计模式呢?
继承实现的增强类和修饰模式实现的增强类有何区别?
继承实现的增强类:
优点:代码结构清晰,而且实现简单
缺点:对于每一个的需要增强的类都要创建具体的子类来帮助其增强,这样会导致继承体系过于庞大。
修饰模式实现的增强类:
优点:内部可以通过多态技术对多个需要增强的类进行增强
缺点:需要内部通过多态技术维护需要增强的类的实例。进而使得代码稍微复杂。