首页 > 代码库 > 装饰者模式

装饰者模式

1、继承实现的增强类和装饰者模式的增强类有何区别?

    继承实现:

      优点:代码结构清晰,实现简单。

      缺点:每一功能都需要创建具体的子类,这样会导致继承体系过于庞大。

    装饰者模式实现:

      优点:内部可以通过多态技术对需要多个增强的类进行增强,使这些装饰类达到互相装饰的效果。

      缺点:需要内部通过多态技术维护需要增强的类的实例,进而导致了代码稍微复杂。

2、继承实现

  1 package other;
  2 
  3 import java.io.BufferedReader;
  4 import java.io.File;
  5 import java.io.FileNotFoundException;
  6 import java.io.FileReader;
  7 import java.io.IOException;
  8 import java.io.Reader;
  9 
 10 /*
 11  装饰者设计模式:增强一个类的功能,而且还可以让这些装饰类互相装饰。
 12  
 13  BufferedReader是不是拓展了FileReader的功能。
 14  BuferedWriter 也是拓展了FileWriter的功能。
 15  
 16  需求1: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有行号。
 17  
 18   需求2:编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有分号。
 19   
 20   需求3: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有双引号。
 21   
 22  
 23  需求4: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有行号+ 分号。
 24   
 25  需求5: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有分号+ 双引号。
 26 
 27  需求6: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有双引号+ 行号。
 28    
 29  需求7: 编写一个类拓展BufferedReader的功能, 增强readLine方法返回 的字符串带有行号+ 分号+双引号。
 30  
 31 ----| Reader
 32 -----------| BufferedReader
 33 ---------------| BufferedLineNum  带行号
 34 ---------------| BufferedSemi    带分号
 35 ---------------| BufferedQuto   带双引
 36 ---------------| 子类.. 
 37 ---------------|
 38 
 39 增强一个类的功能时候我们可以选择使用继承:
 40     
 41     通过继承实现增强一个类的功能优点:   代码结构清晰,通俗易懂。
 42     
 43     缺点: 使用不灵活,会导致继承的体系过于庞大。
 44     
 45  
 46  
 47  
 48  */
 49 class BufferedLineNum extends BufferedReader{
 50     //行号
 51     int count = 1 ;
 52 
 53     public BufferedLineNum(Reader in) {
 54         super(in);
 55     }
 56     
 57     @Override
 58     public String readLine() throws IOException {
 59         String line = super.readLine(); 
 60         if(line ==null){
 61             return null;
 62         }
 63         line = count+" "+ line;
 64         count++;
 65         return line;
 66     }    
 67 }
 68 
 69 
 70 //带分号的缓冲输入字符流
 71 class BufferedSemi extends BufferedReader{
 72 
 73     public BufferedSemi(Reader in) {
 74         super(in);
 75     }
 76     
 77     @Override
 78     public String readLine() throws IOException {
 79         String line =  super.readLine();
 80         if(line==null){
 81             return null;
 82         }
 83         line = line+";";
 84         return line;
 85     }
 86 }
 87 
 88 
 89 //带双引号的缓冲输入字符流
 90 class  BufferedQuto extends BufferedReader{
 91 
 92     public BufferedQuto(Reader in) {
 93         super(in);
 94     }
 95     
 96     @Override
 97     public String readLine() throws IOException {
 98         String line = super.readLine();
 99         if(line==null){
100             return null;
101         }
102         line = "\""+line+"\"";
103         return line;
104     }
105 }
106 
107 
108 
109 
110 
111 public class Demo1 {
112 
113     public static void main(String[] args) throws IOException {
114         File file = new File("F:\\Demo1.java");
115         //建立数据的输入通道
116         FileReader fileReader = new FileReader(file);
117         //建立带行号的缓冲输入字符流
118         BufferedLineNum bufferedLineNum = new BufferedLineNum(fileReader);
119         
120         //带有分号的缓冲输入字符流
121         BufferedSemi bufferedSemi = new BufferedSemi(fileReader);
122         
123         //带有双引号的缓冲输入字符流
124         BufferedQuto bufferedQuto = new BufferedQuto(fileReader);
125        
127         String line = null;
128         while((line = bufferedQuto.readLine())!=null){
129             System.out.println(line);
130         }
131         
132     }
133     
134 }

3、装饰着模式实现

package other;

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 bufferedReader;
    
    int count = 1;
    
    public BufferedLineNum2(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 BufferedSemi2 extends BufferedReader{  //为什么要继承?  是为了让这些装饰类的对象可以作为参数进行传递,达到互相装饰 的效果。

    //在内部维护一个被装饰类的引用。
    BufferedReader bufferedReader;
        
    
    public BufferedSemi2(BufferedReader bufferedReader){ // new BuffereLineNum();
        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 Demo2 {
    
    public static void main(String[] args) throws IOException {
        File file = new File("F:\\Demo1.java");
        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 = bufferedQuto2.readLine())!=null){
            System.out.println(line);
        }
       
    }
    
}

4、作业

 1 package other;
 2 
 3 /*练习:
 4     一家三口每个人都会工作,儿子的工作就是画画,母亲的工作就是在儿子的基础上做一个增强,不单止可以画画,还可以上涂料。
 5     爸爸的工作就是在妈妈基础上做了增强,就是上画框。
 6 */
 7 
 8 interface Work{
 9     
10     public void work();
11 }
12 
13 class Son implements Work{
14 
15     @Override
16     public void work() {
17         System.out.println("画画...");
18     }
19 }
20 
21 
22 class Mather implements Work{
23 
24     //需要被增强的类。
25     Work worker;
26     
27     public Mather(Work worker){
28         this.worker = worker;
29     }
30     
31     @Override
32     public void work() {
33         worker.work();
34         System.out.println("给画上颜色..");
35     }
36 }
37 
38 
39 class Father implements Work{
40 
41     //需要被增强的类的引用
42     Work worker;
43     
44     public Father(Work worker){
45         this.worker = worker;
46     }
47     
48     
49     @Override
50     public void work() {
51         worker.work();//调用其他类的方法
52         System.out.println("上画框...");
53     }
54     
55 }
56 
57 
58 public class Demo3 {
59     
60     public static void main(String[] args) {
61         Son s = new Son();
62 //        s.work();
63         Mather m = new Mather(s);
64 //        m.work();
65         Father f = new Father(s);
66         f.work();
67         
68         
69     }
70 }

 

装饰者模式