老生常谈:装饰者模式
???? 網站新聞模塊中應用裝飾模式
???? 本人現今對設計模式特別感興趣,因為它的功能實在是太吸引人啦.設計模式一般說來是為了增加系統的可擴展性及維護性。在一般的門戶網站中都會有新聞展示這個功能模塊。
???? 具體案例:有存儲在數據庫中的新聞,有存儲在XML文件中的新聞(一般都是推薦新聞,內容比較少)。
???? 在沒有接觸設計模式時,都是針對具體實現編程,讀取數據庫新聞時直接寫一個基于數據庫的方法,讀取推薦新聞時再寫一個基于XML的方法,兩種方法之間沒有任何的關系.當時覺的這樣實現也沒什么不好。可是你總會發現這兩種方法在實現上有很多相同的地方,都是讀取出一個新聞標題集合來綁定數據源,只是取數據源的方法不同而已。為了方便管理,我們可以定義一個統一的接口來約束這兩種方法。這種做法也足夠滿足讀取不同載體的新聞要求。可是如果在讀取新聞時要做其它的操作呢?例如:給讀取出來的新聞的人氣加一。這個時候我們就要修改原程序,這樣有背于"對擴展開放,對修改關閉"的編程原則。如何解決呢?這就是裝飾者模式出場的時候了。
???? 裝飾者模式 :動態地將責任附加到對象上.若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。
???? 裝飾者模式類圖:
??????????
??
?
??? 問題:? 說裝飾者模式比用繼承會更富有彈性,在類圖中不是一樣用到了繼承了嗎?
??? 說明:裝飾者和被裝飾者之間必須是一樣的類型,也就是要有共同的超類。在這里應用繼承并不是實現方法的復制,而是實現類型的匹配。因為裝飾者和被裝飾者是同一個類型,因此裝飾者可以取代被裝飾者,這樣就使被裝飾者擁有了裝飾者獨有的行為。根據裝飾者模式的理念,我們可以在任何時候,實現新的裝飾者增加新的行為。如果是用繼承,每當需要增加新的行為時,就要修改原程序了。
???? 說了一些裝飾者模式的類圖和概念,下面就要講新聞模塊和裝飾者模式的關聯了。
??? 例如:在展示新聞的同時給讀取出來的新聞的人氣加一,同時把新聞標題加入到RSS中,如果是用繼承,就要往超類中增加相應的方法,如果是一個新增行為還是可以忍受的,如果此模塊有不斷增加業務的可能,那是不是要每次都要修改原程序呢?我想所有的朋友都不希望這樣做。我們希望當有新的行為時才往舊對象上加,是在運行時加,并不是一開始就加。
???
??? 解決方案:這里我應用裝飾者模式設計來滿足這種不斷新增業務的需求:
????
??? 1:定義根據不同載體讀取新聞方法的抽象類:
???
public?abstract??class?Component_News
????{
???????/**////?<summary>
????????///?取新聞
????????///?</summary>
????????///?<returns></returns>
???????public?abstract?List<News>?getListOfNews();
????}
????
??? 2:基于數據庫讀取新聞的類:
??
Codepublic?class?DB_News?:?Component_News
????{
???????/**////?<summary>
???????///?從數據庫中取新聞
???????///?</summary>
???????///?<returns></returns>
???????public?override??List<News>?getListOfNews()
???????{
???????????List<News>?_list?=?new?List<News>();
???????????//從數據庫中取得數據填充到_list?中
???????????Console.WriteLine("從數據庫中取得數據填充到_list?中");
???????????return?_list;
???????
???????}
????}
?????
??? 3:基于XML讀取新聞:
?????
Code/**////?<summary>
????????///?從XML中取新聞
????????///?</summary>
????????///?<returns></returns>
????????public?override?List<News>?getListOfNews()
????????{
????????????List<News>?_list?=?new?List<News>();
????????????//從XML中取得數據填充到_list?中
????????????Console.WriteLine("從XML中取得數據填充到_list?中");
????????????return?_list;
????????}
????
??? 4:新聞實體類:
?
Codepublic??class?News
????{
???????/**////?<summary>
???????///?新聞標題
???????///?</summary>
???????private?string?_news_title;
???????public?string?news_title
???????{
???????????get?{?return?this._news_title;?}
???????????set?{?this._news_title?=?value;?}
???????
???????}
???????/**////?<summary>
???????///?新聞內容
???????///?</summary>
???????private?string?_news_content;
???????public?string?news_content
???????{
???????????get?{?return?this._news_content;?}
???????????set?{?this._news_content?=?value;?}
???????}
????}
???
??? 5:下面是抽象裝飾類:
public?abstract?class?Decorator_News?:Component_News?
????{
????????/**////?<summary>
????????///?取新聞
????????///?</summary>
????????///?<returns></returns>
???????public?override?List<News>?getListOfNews()
???????{
???????????return?this._Component_News.getListOfNews();
???????}
???????private?Component_News?_Component_News;
???????public?Decorator_News(Component_News?_Component_News2)
???????{
???????????this._Component_News?=?_Component_News2;
???????
???????}
???????
????}
??????
??? 6:擴展新聞組件: 給新聞添加人氣的方法類:
public??class?ConcreteDecortor_AddAmount:Decorator_News?
????{
???????public?string????AddAmount()
???????{
???????????//新聞人氣加一
???????????Console.WriteLine("新聞人氣已經加一");
???????????return?"新聞人氣已經加一";
???????
???????}
???????public?ConcreteDecortor_AddAmount(Component_News?_Component_News):?base(_Component_News)
???????{
???????}
???????/**////?<summary>
???????///?重寫父類中讀取新聞的方法
???????///?</summary>
???????///?<returns></returns>
???????public?override?List<News>?getListOfNews()
???????{
???????????//此處加入擴展代碼:新聞人氣加一
???????????AddAmount();
???????????return??base.getListOfNews();??????????
???????
???????}
????
????}
????
??? 7:擴展新聞組件: 把新聞加入到RSS中的方法類:
public??class?ConcreteDecortor_AddRss?:?Decorator_News?
????{
???????/**////?<summary>
???????///?將新聞標題加入到RSS中
???????///?</summary>
???????///?<returns></returns>
???????public?string?AddRss()
???????{
???????????//新聞標題已經被RSS收錄
???????????Console.WriteLine("新聞標題已經加入到RSS中");
???????????return?"";
???????
???????}
???????public?ConcreteDecortor_AddRss(Component_News?_Component_News):?base(_Component_News)
???????{
???????}
???????/**////?<summary>
???????///?重寫父類中讀取新聞的方法
???????///?</summary>
???????///?<returns></returns>
???????public?override?List<News>?getListOfNews()
???????{
???????????//此處加入擴展代碼:將新聞標題加入到RSS中
???????????AddRss();
???????????return?base.getListOfNews();
???????}
????}
???
??? 8:客戶端調用:為了說明問題,本人就選用控制臺程序來說明.
Codestatic?void?Main(string[]?args)
????????{
????????????//數據庫方式取新聞
????????????Component_News?_Component_News?=?new?DB_News();
????????????//擴展了展示新聞標題的同時增加此新聞人氣的方法
????????????Decorator_News?_Decorator_News?=?new?ConcreteDecortor_AddAmount(_Component_News);
????????????//擴展了展示新聞標題的同時同時將新聞標題加入RSS中的方法
????????????_Decorator_News?=?new?ConcreteDecortor_AddRss(_Decorator_News);
????????????_Decorator_News.getListOfNews();
????????????Console.ReadKey();
????????}
???
??? 9:運行效果:這樣就可以為斷的添加新的裝飾者來裝飾我們的新聞組件了,并不需要修改新聞組件,而只要添加新的類.Decorator模式采用對象組合大大的降低了系統的耦合度。
?
??????裝飾者模式的問題及解決:用裝飾者實例化組件時,將增加代碼的復雜度,一旦應用了裝飾者模式,不只需要實例化組件,還要把組件包裝進裝飾者,而這樣的裝飾者有多少個是不確定的。這里可以應用工廠模式來實例化組件來簡化操作。
???? 注:
??????? 本文參考:<<Head First 設計模式>>
轉載于:https://www.cnblogs.com/ASPNET2008/archive/2008/06/15/1222724.html
總結
以上是生活随笔為你收集整理的老生常谈:装饰者模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 转:SharePoint站点中用户信息与
- 下一篇: netuse 用法