1. 程式人生 > >設計模式:三段程式碼讓你理解 裝飾者模式

設計模式:三段程式碼讓你理解 裝飾者模式

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();
	}

}