装饰者设计模式:增强一个类的功能,而且还可以让这些装饰类互相装饰
装饰者设计模式的步骤:
1.在装饰类内部维护一个被装饰类的引用(哪个类需要被装饰,就在那个类里面维护这个类的引用)
2.让装饰类有一个共同的父类或父接口(继承或实现)
目的:为了让这些装饰类可以作为参数进行传递,从而达到互相装饰的效果
3.编写装饰类的构造方法(把被装饰类作为参数传递进来)
目的:把对象传给被装饰类(即把维护的那个装饰类的引用变量进行初始化)
4.自己实现方法
继承:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
/*
装饰者设计模式:增强一个类的功能,而且还可以让这些装饰类互相装饰。
装饰者设计模式的步骤:
1. 在装饰类的内部维护一个被装饰类的引用。
2. 让装饰类有一个共同的父类或者是父接口。
需求1: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有行号。
需求2:编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有分号。
需求3: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有双引号。
需求4: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有行号+ 分号。
需求5: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有分号+ 双引号。
需求6: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有双引号+ 行号。
需求7: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有行号+ 分号+双引号。
继承实现的增强类和修饰模式实现的增强类有何区别?
继承实现的增强类:
优点:代码结构清晰,而且实现简单.
缺点:对于每一个的需要增强的类都要创建具体的子类来帮助其增强,这样会导致继承体系过于庞大。
修饰模式实现的增强类:
优点:内部可以通过多态技术对多个需要增强的类进行增强, 可以是这些装饰类达到互相装饰的效果。使用比较灵活。
缺点:需要内部通过多态技术维护需要被增强的类的实例。进而使得代码稍微复杂。
*/
import java.io.IOException;
//带行号的缓冲输入字符流
class BufferedLineNum2 extends BufferedReader{
//在内部维护一个被装饰类的引用。
BufferedReader aaaa;
int count = 1;
public BufferedLineNum2(BufferedReader bufferedReader){ //后面传的是bufferedLineNum
super(bufferedReader);// 注意: 该语句没有任何的作用,只不过是为了让代码不报错。
aaaa = bufferedReader;
}
@Override
public String readLine() throws IOException{
String line = aaaa.readLine(); //实质上:bufferedLineNum.readLine(),因为多态,所以没必要这样写
if(line==null){ //aaaa.readLine是BufferedReader aaaa这个变量所指向的对象的readlin方法
//这个readline方法是创建对象时传入的缓冲类的对象的readline方法,传入什么对象,就调用那个对象的方法,与父类无关
return null;
}
line = count+" "+line;
count++;
return line;
}
}
//带分号缓冲输入字符流
class BufferedSemi2 extends BufferedReader{ //为什么要继承? 是为了让这些装饰类的对象可以作为参数进行传递,达到互相装饰 的效果。
//在内部维护一个被装饰类的引用。
BufferedReader bufferedReader;
public BufferedSemi2(BufferedReader bufferedReader){ // new BuffereLineNum(); 后面传的是bufferedLineNum
super(bufferedReader);// 注意: 该语句没有任何的作用,只不过是为了让代码不报错。
this.bufferedReader = bufferedReader;
}
public String readLine() throws IOException{
String line = bufferedReader.readLine(); //如果这里的ReadLine方法是调用了buffereLineNum的readLine方法,问题马上解决。
if(line==null){
return null;
}
line = line +";";
return line;
}
}
//缓冲类带双引号
class BufferedQuto2 extends BufferedReader{
//在内部维护一个被装饰的类
BufferedReader bufferedReader;
public BufferedQuto2(BufferedReader bufferedReader){ //new BufferedSemi2();
super(bufferedReader) ; //只是为了让代码不报错..
this.bufferedReader = bufferedReader;
}
public String readLine() throws IOException{
String line = bufferedReader.readLine(); //如果这里的ReadLine方法是调用了buffereLineNum的readLine方法,问题马上解决。
if(line==null){
return null;
}
line = "\""+line +"\"";
return line;
}
}
public class Demo {
public static void main(String[] args) throws IOException {
File file = new File("F:\\z.txt");
FileReader fileReader = new FileReader(file);
//建立缓冲输入字符流
BufferedReader bufferedReader = new BufferedReader(fileReader);
//建立带行号的缓冲输入字符流
BufferedLineNum2 bufferedLineNum = new BufferedLineNum2(bufferedReader);
//带分号的缓冲输入字符流
// BufferedSemi2 bufferedSemi2 = new BufferedSemi2(bufferedLineNum);
//
// //带双引号的缓冲输入字符流
// BufferedQuto2 bufferedQuto2 = new BufferedQuto2(bufferedSemi2);
String line = null;
while((line = bufferedLineNum.readLine())!=null){
System.out.println(line);
}
}
}
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
//带行号的缓冲输入字符流
class BufferedLineNum extends BufferedReader{
int count = 1;
BufferedReader bufferedReader;
public BufferedLineNum(BufferedReader bufferedReader) {
super(bufferedReader);
this.bufferedReader = bufferedReader;
}
public String readLine()throws IOException{
String line = bufferedReader.readLine();
if(line == null){
return null;
}
line = count+" "+line;
count++;
return line;
}
}
//带分号缓冲输入字符流
class BufferedSemi extends BufferedReader{
BufferedReader bufferedReader;
public BufferedSemi(BufferedReader bufferedReader){
super(bufferedReader);
this.bufferedReader = bufferedReader;
}
public String readLine()throws IOException{
String line = bufferedReader.readLine();
if(line == null){
return null;
}
line = line + ";";
return line;
}
}
//带双引号缓冲输入字符流
class BufferedQuto extends BufferedReader{
BufferedReader bufferedReader;
public BufferedQuto(BufferedReader bufferedReader){
super(bufferedReader);
this.bufferedReader = bufferedReader;
}
public String readLine()throws IOException{
String line = bufferedReader.readLine();
if(line == null){
return null;
}
line = "\""+line+"\"";
return line ;
}
}
public class Demo1 {
public static void main(String[] args) throws IOException {
File file = new File("E:\\a.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
BufferedLineNum bufferedLineNum = new BufferedLineNum(bufferedReader);
BufferedSemi bufferedSemi = new BufferedSemi(bufferedLineNum); //多态:用父类声明的引用类型变量指向子类的对象
BufferedQuto bufferedQuto = new BufferedQuto(bufferedSemi); // 通过参数的传递,达到互相装饰的效果
String line = null;
//带行号
/*while((line = bufferedLineNum.readLine())!=null){
System.out.println(line);
}*/
//带分号
/*while((line = bufferedSemi.readLine())!=null){
System.out.println(line);
}*/
//带双引号
while((line = bufferedQuto.readLine())!=null){
System.out.println(line);
}
}
}
实现:
1.维护被装饰类的引用
2.用构造方法把被装饰的类作为参数传递进来,即初始化被装饰类
3.实现
4.通过参数传递实现互相装饰 (因为这些类都有一个共同的父接口 所以可以相互传递)
package other;
/*练习:
一家三口每个人都会工作,儿子的工作就是画画,母亲的工作就是在儿子的基础上做一个增强,不单止可以画画,还可以上涂料。
爸爸的工作就是在妈妈基础上做了增强,就是上画框。
*/
interface Work{
public void work();
}
class Son implements Work{
@Override
public void work() {
System.out.println("画画...");
}
}
class Mather implements Work{
//需要被增强的类。
Work worker;
public Mather(Work worker){
this.worker = worker;
}
@Override
public void work() {
worker.work();
System.out.println("给画上颜色..");
}
}
class Father implements Work{
//需要被增强的类的引用
Work worker;
public Father(Work worker){
this.worker = worker;
}
@Override
public void work() {
worker.work();
System.out.println("上画框...");
}
}
public class Demo3 {
public static void main(String[] args) {
Son s = new Son();
// s.work();
Mather m = new Mather(s);
// m.work();
Father f = new Father(s);
f.work();
}
}