設計模式:三段程式碼讓你理解 裝飾者模式
阿新 • • 發佈:2018-11-14
package com.zx.b_decorator; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.Reader; /* * * 需求1: 編寫一個類對 BufferedReader的功能進行增強,增強readLine方法,返回資料帶有行號 * 需求2: 編寫一個類 對 BufferedReader的功能進行增強,增強readLine方法,返回資料帶有分號 * 需求3: 編寫一個類 對 BufferedReader的功能進行增強,增強readLine方法,返回資料帶有雙引號 * 需求4: 編寫一個類 對 BufferedReader的功能進行增強,增強readLine方法,返回資料帶有行號+分號 * 需求5: 編寫一個類 對 BufferedReader的功能進行增強,增強readLine方法,返回資料帶有行號+雙引號 * 需求6: 編寫一個類 對 BufferedReader的功能進行增強,增強readLine方法,返回資料帶有分號+雙引號 * 需求7: 編寫一個類 對 BufferedReader的功能進行增強,增強readLine方法,返回資料帶有行號+分號+雙引號 * * 增強一個類的功能: * 通過繼承 增強一個類的功能的優點:程式碼結構清晰,簡單 * 缺點: 程式碼不靈活,而且導致 繼承體系 過於龐大 * * 解決方案:使用繼承,通過子類 去增強其功能 * * * * * * --|BufferedReader * --| BufferedLineNum readLine方法加行號 * --| BufferedSemi readLine方法加分號 * --| BufferedQuto readLine方法加雙引號 * --| * --| * --| * * * * */ //加行號的緩衝類 class BufferedLineNum extends BufferedReader{ int count = 1; // 行號 public BufferedLineNum(Reader in) { super(in); } @Override public String readLine() throws IOException { String line = super.readLine(); //讀到檔案末尾 if(line == null){ return null; } return count++ +":"+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; } return line+";"; } } //帶有雙引號的緩衝類 class BufferedQuto extends BufferedReader{ public BufferedQuto(Reader in) { super(in); } @Override public String readLine() throws IOException { String line = super.readLine(); //讀到檔案末尾 if(line == null){ return null; } return "\""+line+"\""; } } //行號+分號 class BufferedSemiAndLineNum extends BufferedLineNum{ public BufferedSemiAndLineNum(Reader in) { super(in); // TODO Auto-generated constructor stub } } //行號+雙引號 class BufferedLineNumAndQuto extends BufferedLineNum{ public BufferedLineNumAndQuto(Reader in) { super(in); // TODO Auto-generated constructor stub } } //行號+雙引號+分號 class BufferedLineNumAndQutoAndSemi extends BufferedLineNumAndQuto{ public BufferedLineNumAndQutoAndSemi(Reader in) { super(in); // TODO Auto-generated constructor stub } } public class Demo1 { public static void main(String[] args) throws IOException { File file = new File("d://user.txt"); //行號 //BufferedLineNum bln = new BufferedLineNum(new FileReader(file)); //分號 BufferedSemi bs = new BufferedSemi(new FileReader(file)); //雙引號 //BufferedQuto bq = new BufferedQuto(new FileReader(file)); String line = null; while((line = bs.readLine())!=null){ System.out.println(line); } } }
/* * 需求: 在每行前面加一個行號 * 解決方案: 希望readLine方法返回給我們的就是一個帶需要的內容 * 對BufferedReader的 readLine方法進行增強,這時候可以使用裝飾者模式 * * 裝飾者模式 * 概念: 裝飾者 和 被裝飾者 * BufferedReader 就是 被裝飾者 * * 步驟: * 1)編寫一個 BufferedReader裝飾者類,繼承被裝飾者類(不能是final的) * 2)在裝飾者類中定義一個成員變數,用於接收被裝飾者物件 * 3)在裝飾者類的構造方法中傳入被裝飾者物件 * 使用第二步定義的成員變數接收被傳入的 被裝飾者 * 4)在裝飾者類中重寫被裝飾者類方法,對方法進行增強 * * 注意: * 1.讓裝飾者與被裝飾者 有一個共同的父類或者父介面 * * 裝飾者設計模式 * 好處: 利用了多型達到了 類 與 類 之間的互相修飾,比較靈活 * 缺點: 程式碼結構不清晰,難以理解 * * * * * * */ //加行號的緩衝類 class BufferedLineNum2 extends BufferedReader{ BufferedReader br; int count = 1; public BufferedLineNum2(BufferedReader br) { super(br); this.br= br; } @Override public String readLine() throws IOException { //被裝飾者 的 readLine方法(就是 沒有被增強的readLine方法) String line = br.readLine(); if(line == null){ return null; } return count++ +":"+line; } } //帶雙引號的緩衝流 class BufferedQuto2 extends BufferedReader{ BufferedReader br; public BufferedQuto2(BufferedReader br) { super(br); this.br= br; } @Override public String readLine() throws IOException { //被裝飾者 的 readLine方法(就是 沒有被增強的readLine方法) String line = br.readLine(); if(line == null){ return null; } return "\""+line+"\""; } } //帶分號的緩衝流 class BufferedSemi2 extends BufferedReader{ BufferedReader br; public BufferedSemi2(BufferedReader br) { super(br); this.br= br; } @Override public String readLine() throws IOException { //被裝飾者 的 readLine方法(就是 沒有被增強的readLine方法) String line = br.readLine(); if(line == null){ return null; } return line+";"; } } public class Demo2 { public static void main(String[] args) throws IOException { //被裝飾者物件 BufferedReader br = new BufferedReader(new FileReader(new File("d://user.txt"))); //建立一個帶行號的緩衝輸入字元流:傳入被裝飾者物件 BufferedLineNum2 lineNum = new BufferedLineNum2(br); //建立一個帶雙引號的緩衝輸入字元流:傳入被裝飾者物件 BufferedQuto2 quto = new BufferedQuto2(br); //建立一個帶分號的緩衝輸入字元流:傳入被裝飾者物件 BufferedSemi2 semi = new BufferedSemi2(br); //行號+雙引號 // BufferedQuto2 作為 修飾者,BufferedLineNum2作為被修飾者 BufferedQuto2 qutoAndLinenum = new BufferedQuto2(lineNum); //行號+分號 BufferedSemi2 semiAndLinenum = new BufferedSemi2(lineNum); //分號+雙引號 //分號+雙引號+行號 String line = null; while((line = semiAndLinenum.readLine())!=null){ System.out.println(line); } } }
/* * 需求:一家三口 畫一幅畫,兒子負責繪畫 * 媽媽負責上色,塗顏料 * 爸爸負責上畫框 * * * */ interface Draw{ void draw(); } class Son implements Draw{ @Override public void draw() { System.out.println("兒子正在畫畫..."); } } class Mother implements Draw{ //在內部維護一個 需要被增強的類 Draw d; public Mother(Draw d){ this.d = d; } @Override public void draw() { //被裝飾者 原先的功能 d.draw(); //對 功能進行增強 System.out.println("媽媽上塗料..."); } } class Father implements Draw{ Draw d; public Father(Draw d){ this.d = d; } @Override public void draw() { d.draw(); System.out.println("爸爸上畫框..."); } } public class Demo3 { public static void main(String[] args) { Son s = new Son(); Mother m = new Mother(s); Father f = new Father(m); f.draw(); } }