設計模式4 裝飾器模式Decorator

2021-09-27 07:10:11 字數 3664 閱讀 8492

裝飾器模式屬於"單一職責"模式.

在軟體元件的設計中,如果責任劃分不清晰,使用繼承得到的結果,往往是隨著需求的變化,子類急劇膨脹,同時充斥著重複**,這是**的bad smell.

典型的單一職責模式:decorator,bridge.這兩種模式表現出了很強的"單一職責模式的味道".本文中我們討論decorator模式.

在某些情況下,我們可能會"過度的使用繼承來擴充套件物件的功能",由於繼承為型別引入了靜態特質,使得這種擴充套件方式缺乏靈活性;並且隨著子類的增多(擴充套件功能的增多),各種子類的組合(擴充套件功能的組合)會導致更多子類的膨脹.

如何使物件功能的擴充套件能夠根據需要動態實現,同時避免擴充套件功能的增多帶來的子類膨脹問題?從而使得任何功能擴充套件變化所帶來的影響最低.

考慮設計乙個io的庫,主要是一些流操作.可以首先定義乙個基類stream,

//業務操作

class

stream

};

基於stream可以定義檔案流,網路流,記憶體流等派生類,然後重寫實現基類的成員函式.

class

filestream

:public stream

virtual

void

seek

(int postion)

virtual

void write (

char data)};

class

networkstream

:public stream

virtual

void

seek

(int postion)

virtual

void write (

char data)};

class

memorystream

:public stream

virtual

void

seek

(int postion)

virtual

void write (

char data)

};

現在我們想給檔案流,網路流,進行功能擴充套件,比如在流讀寫的過程中,新增額外的加密操作,這個是時候應該怎麼處理?

首先我們先看用繼承的的方式來解決這個問題.

首先是對檔案讀寫進行加密,這個時候會增加3個類,分別對filestream,networkstream,memorystream

class

cryptofilestream

:public filestream

virtual

void

seek

(int postion)

virtual

void write (

char data)};

class

cryptonetworkstream

:public networkstream

virtual

void

seek

(int postion)

virtual

void write (

char data)};

class

cryptomemorystream

:public memorystream

virtual

void

seek

(int postion)

virtual

void write (

char data)

};

可以看到,這個時候類增多,並且存在很多重複**,這種設計不好.考慮用組合的方式,不用繼承.

我們這個時候不用繼承,採用組合的模式,在加密的類中增加乙個成員變數.這樣的話可以用乙個加密的類,替換掉三個派生類,加密的檔案型別取決於成員stream_的取值,可以相應的對filestream,network,memory進行加密.

class

cryptostream

virtual

void

seek

(int postion)

virtual

void write (

char data)

};

這個時候我們需要考慮一下,cryptostream中的成員函式還都是虛函式,這個是不合理的,因為它並不是基類,為了保持介面一致性,我們需要讓他繼承stream,

class

cryptostream

:public stream

virtual

char

read

(int number)

virtual

void

seek

(int postion)

virtual

void write (

char data)

};

這個時候就出現了乙個非常奇妙的現象,也就是cryptostream 既繼承了基類,同時也有乙個成員變數是基類的指標.

再進一步可以將stream* stream_字段上移,定義乙個decorator

class

decorator

:public stream

protected

: stream* stream_;};

class

cryptostream

:public decorator

virtual

char

read

(int number)

virtual

void

seek

(int postion)

virtual

void write (

char data)

};

動態地(組合)給乙個物件增加一些額外的職責,就增加功能而言,decorator模式比生成子類(繼承)更加靈活(消除重複**,減少子類個數)

通過採用組合而非繼承的方式,decorator模式實現了在執行時動態擴充套件物件功能的能力,而且可以根據需要擴充套件多個功能,避免了使用繼承帶來的"靈活性差"和"多子類衍生問題".

decorator 類在介面上變現為 is a component 的繼承關係,即decorator類繼承了component類的所具有的介面.但是在實現上又表現為has a component的關係,即decorator類又使用了另外乙個component類.繼承是為了介面規範,組合是為了呼叫具體的實現類.

decorator 模式並非解決,多子類衍生的多繼承問題,decorator模式應用的要點在於解決,主體類在多個方向上的擴充套件功能.

設計模式 裝飾器模式

裝飾器模式 decorator pattern 允許向乙個現有的物件新增新的功能,同時又不改變其結構。這種型別的設計模式屬於結構型模式,它是作為現有的類的乙個包裝。這種模式建立了乙個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。public inte ce playe...

設計模式 裝飾器模式

裝飾者模式的應用場景 裝飾者模式 decorator pattern 是指在不改變原有物件的基礎之上,將功能附加到物件上,提供了比繼承更有彈性的替代方案 擴充套件原有物件的功能 屬於結構型模式。裝飾者模式在我們生活中應用也比較多如給煎餅加雞蛋 給蛋糕加上一些水果 給房子裝修等,為物件擴充套件一些額外...

設計模式 裝飾器模式

定義 裝飾模式可以動態的給乙個物件增加一些額外的功能 增強功能 相比於繼承,裝飾模式能對不支援繼承的類進行增強 並且比繼承更靈活,不需要生成大量的子類。角色 實現 public abstract class house public abstract void sleep public class ...