java設計模式-裝飾模式

裝飾模式可以在不改變一個對象本身功能的基礎上給對象增加額外的新行爲,在現實生活中,這種情況也到處存在,例如一張照片,我們可以不改變照片本身,給它增加一個相框,使得它具有防潮的功能,而且用戶可以根據需要給它增加不同類型的相框,甚至可以在一個小相框的外面再套一個大相框。裝飾模式是一種用於替代繼承的技術,它通過一種無須定義子類的方式來給對象動態增加職責,使用對象之間的關聯關係取代類之間的繼承關係。在裝飾模式中引入了裝飾類,在裝飾類中既可以調用待裝飾的原有類的方法,還可以增加新的方法,以擴充原有類的功能。
裝飾模式(Decorator Pattern):動態地給一個對象增加一些額外的職責,就增加對象功能來說,裝飾模式比生成子類實現更爲靈活。裝飾模式是一種對象結構型模式。

包含角色:

① Component(抽象構件):它是具體構件和抽象裝飾類的共同父類,聲明瞭在具體構件中實現的業務方法,它的引入可以使客戶端以一致的方式處理未被裝飾的對象以及裝飾之後的對象,實現客戶端的透明操作。
② ConcreteComponent(具體構件):它是抽象構件類的子類,用於定義具體的構件對象,實現了在抽象構件中聲明的方法,裝飾器可以給它增加額外的職責(方法)。
③ Decorator(抽象裝飾類):它也是抽象構件類的子類,用於給具體構件增加職責,但是具體職責在其子類中實現。它維護一個指向抽象構件對象的引用,通過該引用可以調用裝飾之前構件對象的方法,並通過其子類擴展該方法,以達到裝飾的目的。
④ ConcreteDecorator(具體裝飾類):它是抽象裝飾類的子類,負責向構件添加新的職責。每一個具體裝飾類都定義了一些新的行爲,它可以調用在抽象裝飾類中定義的方法,並可以增加新的方法用以擴充對象的行爲。

下面,我們將以“圖形界面窗體”爲例,來對裝飾模式進一步理解學習。

/**
 * 抽象組件產品
 */
public abstract class Component {

	public abstract void display();
}


/**
 * 具體組件類:窗體組件
 */
public class Window extends Component {

	@Override
	public void display() {
		System.out.println("顯示窗體!");
	}

}


/**
 * 具體組件類:文本框組件
 */
public class TextBox extends Component {

	@Override
	public void display() {
		System.out.println("文本框顯示!");
	}

}
/**
 * 構件裝飾類:抽象裝飾類
 */
public abstract class ComponentDecorator extends Component {

	private Component component; //維持對抽象構建類型的引用
	
	//注入抽象構件類型的對象
	public ComponentDecorator(Component component){ 
		this.component = component;
	}
	
	public void display(){
		component.display();
	}
	
}


/**
 * 具體裝飾者:滾動條裝飾
 */
public class ScrollBarDecorator extends ComponentDecorator {

	public ScrollBarDecorator(Component component) {
		super(component);
	}

	public void display() {
		setScrollBar();
		super.display();
	}
	
	// 具體裝飾方法
	public void setScrollBar() {
		System.out.println("爲構件添加滾動條!");
	}
}


/**
 * 具體裝飾者:黑色邊框裝飾
 */
public class BlackBorderDecorator extends ComponentDecorator {

	public BlackBorderDecorator(Component component) {
		super(component);
	}

	public void display() {
		setBlackBorder();
		super.display();
	}
	
	// 具體裝飾方法
	public void setBlackBorder() {
		System.out.println("爲構件增加黑色邊框!");
	}
}
/**
 * 客戶端調用
 */
public class Client {

	public static void main(String[] args) {
		Component component = new Window();
		Component decorator = new BlackBorderDecorator(component);
		decorator.display();
	}
}

 輸出結果:

爲構件增加黑色邊框!
顯示窗體!

主要優點:

(1) 對於擴展一個對象的功能,裝飾模式比繼承更加靈活性,不會導致類的個數急劇增加。
(2) 可以通過一種動態的方式來擴展一個對象的功能,通過配置文件可以在運行時選擇不同的具體裝飾類,從而實現不同的行爲。
(3) 可以對一個對象進行多次裝飾,通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創造出很多不同行爲的組合,得到功能更爲強大的對象。
(4) 具體構件類與具體裝飾類可以獨立變化,用戶可以根據需要增加新的具體構件類和具體裝飾類,原有類庫代碼無須改變,符合“開閉原則”。

主要缺點:

(1) 使用裝飾模式進行系統設計時將產生很多小對象,這些對象的區別在於它們之間相互連接的方式有所不同,而不是它們的類或者屬性值有所不同,大量小對象的產生勢必會佔用更多的系統資源,在一定程序上影響程序的性能。
(2) 裝飾模式提供了一種比繼承更加靈活機動的解決方案,但同時也意味着比繼承更加易於出錯,排錯也很困難,對於多次裝飾的對象,調試時尋找錯誤可能需要逐級排查,較爲繁瑣。

適用場景:

(1) 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
(2) 當不能採用繼承的方式對系統進行擴展或者採用繼承不利於系統擴展和維護時可以使用裝飾模式。不能採用繼承的情況主要有兩類:第一類是系統中存在大量獨立的擴展,爲支持每一種擴展或者擴展之間的組合將產生大量的子類,使得子類數目呈爆炸性增長;第二類是因爲類已定義爲不能被繼承(如Java語言中的final類)。

 

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