設計模式篇章四——裝飾模式

前言:初學設計模式如果有錯誤請多多指教(Thanks >-<)

裝飾模式的介紹

裝飾模式又稱爲裝飾者模式,是結構型模式中的一種,指的允許向一個現有的類添加新的功能,而又不改變其結構。(就好比對一個對象進行裝飾添加一些東西但又不改變該對象本身的結構)

裝飾模式參與的角色

參與角色 功能
抽象的被裝飾類角色 作爲被裝飾類和裝飾類之間的接口
具體被裝飾角色 實現了被裝飾類
抽象的裝飾類角色 持有一個抽象的被裝飾類角色(實現了抽象的被裝飾類角色)
具體的裝飾類角色 實現了具體裝飾,負責給被裝飾對象進行裝飾(繼承了抽象的的裝飾類角色)

裝飾模式的UML圖

在這裏插入圖片描述

裝飾模式案例

接着篇章三的案例,小明現在選擇使用保溫杯,然後小明決定在網上購買保溫杯,小明看到一家賣保溫杯的點,裏面可以自選保溫杯的顏色(可供自選的顏色有藍色、黑色和藍黑色),現在我們使用裝飾模式來實現這個案例。模塊設計:設計抽象的被裝飾類角色(杯子抽象類)、設計具體被裝飾角色(將杯子類進行實現)、設計抽象的裝飾類角色(將杯子的顏色進行抽象)和設計具體的裝飾類角色(保溫杯可選的顏色)
(1)設計一個抽象的被裝飾類角色(Cup類)

/**
 * 
 * @Introduction 該類是抽象的被裝飾的角色,是一個抽象類
 *
 */
public abstract class Cup {
	public abstract void buyCup();
}

(2)設計一個具體的被裝飾類角色(RealCup類)

/**
 * @Introduction 該類實現了Cup類,是被裝飾的具體對象
 */
public class RealCup extends Cup{
	
	/**重寫買杯子方法*/
	@Override
	public void buyCup(){
		System.out.println("買杯子");
	}
}

(3)設計一個抽象裝飾類角色(DecorateCup類)

/**
 * @Introduction 該類實現了Cup,以及在內部定義了一個Cup類的引用
 */
public abstract class DecorateCup extends Cup{

	protected Cup cup;//該成員變量是被裝飾對象的引用
}

(4)設計一個具體裝飾類角色(BlueCup類)

/**
 * @Introduction 該類是一個具體的裝飾類,實現了抽象的裝飾角色,在該類在構造時就必須傳入被裝飾的對象(裝飾角色單獨存在無意義)
 */
public class BlueCup extends DecorateCup{
	
	/**構造方法,用於在構造該具體類的時候指明被裝飾的對象*/
	public BlueCup(Cup cupp) {
		this.cup=cupp;
	}
	
	/**重寫了買杯子的方法(這裏畫上重點——在重寫的方法中,調用傳入的被裝飾對象的buyCup方法然後加上該具體裝飾類的特有屬性)*/
	@Override
	public void buyCup() {
		this.cup.buyCup();
		System.out.println("顏色選擇:藍色");
	}
}

(5)設計一個具體裝飾類角色(BlackCup類)

/**
 * @Introduction 該類是一個具體裝飾角色,表明小明買的杯子顏色是黑色,實現了抽象的裝飾類角色
 */
public class BlackCup extends DecorateCup{
	/**構造方法,用於在該具體裝飾類創建的時候就表明具體的被裝飾對象*/
	public BlackCup(Cup cupp){
		this.cup=cupp;
	}
	
	/**重寫了Cup類中的買杯子方法(同樣這裏畫重點)*/
	public void buyCup(){
		this.cup.buyCup();
		System.out.println("顏色選擇:黑色");
	}
}

(6)模擬用戶界面代碼

/**
 * @Introduction 該類模擬用戶界面
 */
public class Main {
	public static void main(String[] args){
		RealCup cup=new RealCup();//創建一個具體被裝飾的對象實例
		
	    //小明買藍色的杯子
		BlueCup blueCupOne=new BlueCup(cup);//使用藍色來裝飾這個被裝飾的對象
		blueCupOne.buyCup();
		
		//小明買黑色的杯子
		BlackCup blackCupOne=new BlackCup(cup);
		blackCupOne.buyCup();
		
		//小明買藍色和黑色的杯子
		BlueCup blueCupTwo=new BlueCup(cup);
		BlackCup blackCupTwo=new BlackCup(blueCupTwo);
		blackCupTwo.buyCup();
		
	}
}

案例解析

首先我們考慮不使用設計模式來實現該功能,面對這樣一個功能實現我們可以首先設計一個抽象的杯子類,該類是所有可選顏色杯子類的抽象,然後設計所有的可選杯子的類,並讓所有可選杯子類繼承杯子的抽象類,在該題中我們需要設計3個具體的杯子類,分別是藍色杯子類、黑色杯子類和藍黑色杯子類,然後我們在用戶界面在實例化這些具體杯子類來達到用戶選擇杯子的要求,現在我們來分析一下這種做法的優劣:
優點:開放—封閉原則比較好,該類程序可拓展性比較好(比如要加一個新類型的杯子,直接設計一個相關類繼承杯子類即可)
缺點:代碼不夠靈活,每次我們需要推出一個新的杯子類型都要設計一個新的類;廣泛的使用繼承,提高了程序的耦合性,如果設計到對抽象杯類的修改,則可能會造成不好影響;代碼複用性不高。
下面我們來分析一下使用裝飾模式,在裝飾模式中我們一共有四種角色,對於被裝飾類(包括抽象的和具體的)他們無需知道誰會裝飾他們,他們只需要實現自己的功能即可;對於裝飾類(包括抽象的和具體的),它們同樣無需知道他們裝飾的對象是誰(裝飾對象的決定在用戶界面實現),每一個裝飾類只需要完成好自己裝飾的功能。裝飾模式的優劣分析(重點):
優點:
(1)程序擁有良好的靈活性,由於裝飾可以隨意搭配和組合,不同的裝飾相互搭配會有不同的結果。
(2)可拓展性比較好,就上例來說若商家需要增加粉色的杯子,我們只需要在裝飾類中增加一個新類就好。
(3)複用性比較強,如果我們還有一個玻璃杯類上架(前面是保溫杯類),我們只需要然玻璃杯類繼承抽象杯類,然後就可以在用戶界面使用裝飾類來裝飾玻璃杯。
缺點:
(1)由於程序靈活性的特點,這意味着程序的複雜性會大大增加(如果出現錯誤,由於各個類之間層層裝飾找錯誤比較麻煩——這就是有得必有失吧)
(2)由於裝飾類都在用戶界面和界面邏輯一起實現,所以會導致用戶界面過於雜亂同時會暴露相關類的信息。(可以考慮使用使用半透明或者透明的裝飾類——將裝飾過程進行包裝封閉)
(3)由於各種裝飾類相互裝飾,可能會導致代碼難以理解,過度使用的話會使程序變得很複雜。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章