程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 設計模式學習筆記--裝飾(Decorator)模式

設計模式學習筆記--裝飾(Decorator)模式

編輯:C++入門知識


寫在模式學習之前


什麼是設計模式:在我們進行程序設計時,逐漸形成了一些典型問題和問題的解決方案,這就是軟件模式;每一個模式描述了一個在我們程序設計中經常發生的問題,以及該問題的解決方案;當我們碰到模式所描述的問題,就可以直接用相應的解決方法去解決這個問題,這就是設計模式。

設計模式就是抽象出來的東西,它不是學出來的,是用出來的;或許你根本不知道任何模式,不考慮任何模式,卻寫著最優秀的代碼,即使以“模式專家”的角度來看,都是最佳的設計,不得不說是“最佳的模式實踐”,這是因為你積累了很多的實踐經驗,知道“在什麼場合代碼應該怎麼寫”,這本身就是設計模式。

有人說:“水平沒到,學也白學,水平到了,無師自通”。誠然,模式背熟,依然可能寫不出好代碼,更別說設計出好框架;OOP理解及實踐經驗到達一定水平,同時也意味著總結了很多好的設計經驗,但"無師自通",卻也未必盡然,或者可以說,恰恰是在水平和經驗的基礎上,到了該系統的學習一下“模式”的時候了,學習一下專家總結的結果,印證一下自己的不足,對於提高水平還是很有幫助的。

本系列的設計模式學習筆記,實際是對於《Java與模式》這本書的學習記錄。


裝飾(Decorator)定義


裝飾模式又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關系的一個替代方案。

裝飾模式使用原來被裝飾的類的一個子類的實例,把客戶端的調用委派到被裝飾類。裝飾模式的關鍵在於這種擴展是完全透明的。


結構圖


\


所涉及的角色


(1)抽象構件(Component)角色:給出一個抽象接口,以規范准備接收附加責任的對象。

(2)具體構件(Concrete Component)角色:定義一個將要接收附加責任的類。

(3)裝飾(Decorator)角色:持有一個構件(Component)對象的實例,並定義一個與抽象構件接口一致的接口。雖然Decorator類不是一個抽象類,在實際應用中也不一定是抽象類,但是由於它的功能是一個抽象角色,因此也常常稱它為抽象裝飾。

(4)集體裝飾(Concrete Decorator)角色:負責給構件對象“貼上”附加的責任。


代碼實現

interface Component
{
	//商業方法
	void sampleOp();
}
class ConcreteComponent implements Component
{
	public ConcreteComponent()
	{
		//Write your code
	}
	//商業方法
	public void sampleOp()
	{
		//Write your code
	}
}
class Decorator implements Component
{
	private Component component;
	public Decorator(Component component)
	{
		this.component = component;
	}
	public Decorator()
	{
		//Write your code
	}
	//商業方法
	public void sampleOp()
	{
		component.sampleOp();
	}
}
class ConcreteDecorator extends Decorator
{
	//商業方法
	public void sampleOp()
	{
		super.sampleOp();
	}
}

裝飾模式使用場景


(1)需要擴展一個類的功能,或給一個類增加附加責任。

(2)需要動態地給一個對象增加功能,這些功能可以再動態的撤銷。

(3)需要增加由一些基本功能的排列組合而產生的非常大量的功能,從而使基礎關系變得不現實。

個人感覺,除了JDK中IO類的設計,工作場景中幾乎碰不到裝飾模式的使用,完全不像適配器模式,隨處可見。


使用裝飾模式的優點和缺點


(1)裝飾模式與繼承的目的都是要擴展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。裝飾模式允許系統動態地決定“貼上”一個需要的“裝飾”,或者除掉一個不需要的“裝飾”。繼承關系則不同,繼承關系是靜態的,它在系統運行前就決定了。

(2)通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出更多不同行為的組合。而繼承關系則沒有這個優勢,每一種不同的排列組合均需要事先通過子類的繼承方式設計好。

(3)這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承更加易於出錯。

(4)使用裝飾模式,可以比使用繼承關系需要較少數目的類。使用較少的類,當然使設計比較易於進行。但是,在另一方面,使用裝飾模式會產生比使用繼承關系更多的對象。更多的對象會使得查錯變得困難,特別是這些對象看上去都很相像。


模式的簡化


大多數情況下,裝飾模式的實現都比本節的定義中給出的示意性實現要簡單。對模式進行簡化時,需要注意以下的情況:

(1)一個裝飾類的接口必須與被裝飾類的接口相容。ConcreteDecorator類和ConcreteComponent必須繼承自一個共同的父類,這個在裝飾模式結構圖中就有說明,但是在實際使用時,如果在模式的實現上有所簡化,就必須特別注意這一點。

(2)盡量保持Component作為一個“輕”類。抽象構件的職責是接口而不是存儲數據嗎,注意不要把太多的邏輯和狀態放在Component類裡。Component可以是接口、抽象類或者具體類。

(3)如果只有一個ComcreteComponent類而沒有抽象的Component類(接口),那麼Decorator類經常可以是ConcreteComponent的一個子類,如下圖:

\
由上圖可知,沒有抽象的接口Component也是可以的,但ConcreteComponent就要扮演雙重的角色。

(4)如果只有一個ConcreteDecorator類,那麼就沒有必要建立一個單獨的Decorator類,而可以吧Decorator和ConcreteDecorator的責任合並成一個類。甚至只有兩個ConcreteDecorator類的情況下,也可以這樣做;但是具體裝飾類大於三個的話,使用一個單獨的抽象裝飾類就有必要了,如下圖:

n塊?湤董獸掂農娳秺郫鷌n塊嘷嶂熼ズZ喎?http://www.Bkjia.com/kf編程。裝飾模式對客戶端的透明性要求程序不要聲明一個ConcreteDecorator類型的變量,而應當聲明一個Component類型的變量。

(2)然而,純碎的裝飾模式很難找到。裝飾模式的用意是在不改變接口的前提下,增強所考慮的類的性能。在增強性能的時候,往往需要建立新的公開的方法。這就導致了大多數的裝飾模式的實現都是“半透明”(semi-transparent)的,而不是完全“透明”的。換言之,允許裝飾模式改變接口,增加新的方法。這意味著客戶端可以聲明ConcreteDecorator類型的變量,從而可以調用ConcreteDecorator類才有的方法。

(3)半透明的裝飾模式介於裝飾模式和適配器模式之間的。適配器模式的用意是改變所考慮的類的接口,也可以通過改寫一個或幾個方法,或增加新的方法來增強或改變所考慮的類的功能。大多數的裝飾模式實際上是半透明的裝飾模式,這樣的裝飾模式也稱做“半裝飾、半適配器模式”。
(4)在模式研究圈子裡,所謂半透明的裝飾模式又叫做退化的(degenerate)裝飾模式。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved