欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++設(shè)計(jì)模式之裝飾模式

 更新時(shí)間:2014年10月01日 10:36:17   作者:果凍想  
這篇文章主要介紹了C++設(shè)計(jì)模式之裝飾模式,裝飾模式能夠?qū)崿F(xiàn)動(dòng)態(tài)的為對(duì)象添加功能,是從一個(gè)對(duì)象外部來(lái)給對(duì)象添加功能,需要的朋友可以參考下

前言

在實(shí)際開(kāi)發(fā)時(shí),你有沒(méi)有碰到過(guò)這種問(wèn)題;開(kāi)發(fā)一個(gè)類,封裝了一個(gè)對(duì)象的核心操作,而這些操作就是客戶使用該類時(shí)都會(huì)去調(diào)用的操作;而有一些非核心的操作,可能會(huì)使用,也可能不會(huì)使用;現(xiàn)在該怎么辦呢?

1.將這些非核心的操作全部放到類中,這樣,一個(gè)類就包含了很多核心的操作和一些看似有關(guān),但是又無(wú)關(guān)的操作;這就會(huì)使核心類發(fā)生“爆炸”的現(xiàn)象,從而使核心類失去了一定的價(jià)值,也使使用核心類的客戶在核心操作和非核心操作中掙扎;

2.使用繼承來(lái)擴(kuò)展核心類,需要使用核心類時(shí),直接建立核心類對(duì)象;當(dāng)需要使用核心類擴(kuò)展類時(shí),就建立核心類擴(kuò)展類對(duì)象;這樣貌似是一種很有效的方法;但是由于繼承為類型引入的靜態(tài)特質(zhì),使得這種擴(kuò)展方式缺乏靈活性;同時(shí),又掉入了另一個(gè)陷阱,隨著擴(kuò)展功能的增多,子類也會(huì)增多,各種子類的組合,就會(huì)導(dǎo)致類的膨脹,最后,就會(huì)被淹沒(méi)在類的海洋;此時(shí),也不用我多說(shuō),你是不是想起了橋接模式,橋接模式就是為了適應(yīng)多個(gè)維度的變化而發(fā)生子類“爆炸”的情況,但是,橋接模式是為了適應(yīng)抽象和實(shí)現(xiàn)的不同變化,并不適用于我這里說(shuō)的。那如何是好,這就要說(shuō)到今天總結(jié)的裝飾模式了。

什么是裝飾模式?

在GOF的《設(shè)計(jì)模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書中對(duì)裝飾模式是這樣說(shuō)的:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來(lái)說(shuō),Decorator模式相比生成子類更為靈活。

裝飾模式能夠?qū)崿F(xiàn)動(dòng)態(tài)的為對(duì)象添加功能,是從一個(gè)對(duì)象外部來(lái)給對(duì)象添加功能。通常給對(duì)象添加功能,要么直接修改對(duì)象添加相應(yīng)的功能,要么派生對(duì)應(yīng)的子類來(lái)擴(kuò)展,抑或是使用對(duì)象組合的方式。顯然,直接修改對(duì)應(yīng)的類這種方式并不可取。在面向?qū)ο蟮脑O(shè)計(jì)中,而我們也應(yīng)該盡量使用對(duì)象組合,而不是對(duì)象繼承來(lái)擴(kuò)展和復(fù)用功能。裝飾器模式就是基于對(duì)象組合的方式,可以很靈活的給對(duì)象添加所需要的功能。裝飾器模式的本質(zhì)就是動(dòng)態(tài)組合。動(dòng)態(tài)是手段,組合才是目的??傊b飾模式是通過(guò)把復(fù)雜的功能簡(jiǎn)單化,分散化,然后再運(yùn)行期間,根據(jù)需要來(lái)動(dòng)態(tài)組合的這樣一個(gè)模式。它使得我們可以給某個(gè)對(duì)象而不是整個(gè)類添加一些功能。

UML類圖

Component:定義一個(gè)對(duì)象接口,可以給這些對(duì)象動(dòng)態(tài)地添加職責(zé);

ConcreteComponent:定義一個(gè)具體的Component,繼承自ConcreateComponent,重寫了Component類的虛函數(shù);

Decorator:維持一個(gè)指向Component對(duì)象的指針,該指針指向需要被裝飾的對(duì)象;并定義一個(gè)與Component接口一致的接口;

ConcreteDecorator:向組件添加職責(zé)。

代碼實(shí)現(xiàn):

復(fù)制代碼 代碼如下:

/*
** FileName     : DecoratorPatternDemo
** Author       : Jelly Young
** Date         : 2013/12/19
** Description  : More information, please go to http://www.dbjr.com.cn
*/
#include <iostream>
using namespace std;
class Component
{
public:
     virtual void Operation() = 0;
};
class ConcreteComponent : public Component
{
public:
     void Operation()
     {
          cout<<"I am no decoratored ConcreteComponent"<<endl;
     }
};
class Decorator : public Component
{
public:
     Decorator(Component *pComponent) : m_pComponentObj(pComponent) {}
     void Operation()
     {
          if (m_pComponentObj != NULL)
          {
               m_pComponentObj->Operation();
          }
     }
protected:
     Component *m_pComponentObj;
};
class ConcreteDecoratorA : public Decorator
{
public:
     ConcreteDecoratorA(Component *pDecorator) : Decorator(pDecorator){}
     void Operation()
     {
          AddedBehavior();
          Decorator::Operation();
     }
     void  AddedBehavior()
     {
          cout<<"This is added behavior A."<<endl;
     }
};
class ConcreteDecoratorB : public Decorator
{
public:
     ConcreteDecoratorB(Component *pDecorator) : Decorator(pDecorator){}
     void Operation()
     {
          AddedBehavior();
          Decorator::Operation();
     }
     void  AddedBehavior()
     {
          cout<<"This is added behavior B."<<endl;
     }
};
int main()
{
     Component *pComponentObj = new ConcreteComponent();
     Decorator *pDecoratorAOjb = new ConcreteDecoratorA(pComponentObj);
     pDecoratorAOjb->Operation();
     cout<<"============================================="<<endl;
     Decorator *pDecoratorBOjb = new ConcreteDecoratorB(pComponentObj);
     pDecoratorBOjb->Operation();
     cout<<"============================================="<<endl;
     Decorator *pDecoratorBAOjb = new ConcreteDecoratorB(pDecoratorAOjb);
     pDecoratorBAOjb->Operation();
     cout<<"============================================="<<endl;
     delete pDecoratorBAOjb;
     pDecoratorBAOjb = NULL;
     delete pDecoratorBOjb;
     pDecoratorBOjb = NULL;
     delete pDecoratorAOjb;
     pDecoratorAOjb = NULL;
     delete pComponentObj;
     pComponentObj = NULL;
}

使用場(chǎng)合

1.在不影響其他對(duì)象的情況下,以動(dòng)態(tài)的,透明的方式給單個(gè)對(duì)象添加職責(zé);
2.處理那些可以撤銷的職責(zé);
3.當(dāng)不能采用生成子類的方法進(jìn)行擴(kuò)充時(shí)。一種情況是,可能存在大量獨(dú)立的擴(kuò)展,為支持每一種組合將產(chǎn)生大量的子類,使得子類數(shù)目呈爆炸性增長(zhǎng)。另一種情況可能是因?yàn)轭惗x被隱藏,或類定義不能用于生成子類。

注意事項(xiàng)

1.接口的一致性;裝飾對(duì)象的接口必須與它所裝飾的Component的接口是一致的,因此,所有的ConcreteDecorator類必須有一個(gè)公共的父類;這樣對(duì)于用戶來(lái)說(shuō),就是統(tǒng)一的接口;

2.省略抽象的Decorator類;當(dāng)僅需要添加一個(gè)職責(zé)時(shí),沒(méi)有必要定義抽象Decorator類。因?yàn)槲覀兂3R幚?,現(xiàn)存的類層次結(jié)構(gòu)而不是設(shè)計(jì)一個(gè)新系統(tǒng),這時(shí)可以把Decorator向Component轉(zhuǎn)發(fā)請(qǐng)求的職責(zé)合并到ConcreteDecorator中;

3.保持Component類的簡(jiǎn)單性;為了保證接口的一致性,組件和裝飾必須要有一個(gè)公共的Component類,所以保持這個(gè)Component類的簡(jiǎn)單性是非常重要的,所以,這個(gè)Component類應(yīng)該集中于定義接口而不是存儲(chǔ)數(shù)據(jù)。對(duì)數(shù)據(jù)表示的定義應(yīng)延遲到子類中,否則Component類會(huì)變得過(guò)于復(fù)雜和臃腫,因而難以大量使用。賦予Component類太多的功能,也使得具體的子類有一些它們它們不需要的功能大大增大;

實(shí)現(xiàn)要點(diǎn)

1.Component類在Decorator模式中充當(dāng)抽象接口的角色,不應(yīng)該去實(shí)現(xiàn)具體的行為。而且Decorator類對(duì)于Component類應(yīng)該透明,換言之Component類無(wú)需知道Decorator類,Decorator類是從外部來(lái)擴(kuò)展Component類的功能;

2.Decorator類在接口上表現(xiàn)為“is-a”Component的繼承關(guān)系,即Decorator類繼承了Component類所具有的接口。但在實(shí)現(xiàn)上又表現(xiàn)為“has-a”Component的組合關(guān)系,即Decorator類又使用了另外一個(gè)Component類。我們可以使用一個(gè)或者多個(gè)Decorator對(duì)象來(lái)“裝飾”一個(gè)Component對(duì)象,且裝飾后的對(duì)象仍然是一個(gè)Component對(duì)象;

3.Decortor模式并非解決“多子類衍生的多繼承”問(wèn)題,Decorator模式的應(yīng)用要點(diǎn)在于解決“主體類在多個(gè)方向上的擴(kuò)展功能”——是為“裝飾”的含義;

4.對(duì)于Decorator模式在實(shí)際中的運(yùn)用可以很靈活。如果只有一個(gè)ConcreteComponent類而沒(méi)有抽象的Component類,那么Decorator類可以是ConcreteComponent的一個(gè)子類。如果只有一個(gè)ConcreteDecorator類,那么就沒(méi)有必要建立一個(gè)單獨(dú)的Decorator類,而可以把Decorator和ConcreteDecorator的責(zé)任合并成一個(gè)類。

5.Decorator模式的優(yōu)點(diǎn)是提供了比繼承更加靈活的擴(kuò)展,通過(guò)使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創(chuàng)造出很多不同行為的組合;

6.由于使用裝飾模式,可以比使用繼承關(guān)系需要較少數(shù)目的類。使用較少的類,當(dāng)然使設(shè)計(jì)比較易于進(jìn)行。但是,在另一方面,使用裝飾模式會(huì)產(chǎn)生比使用繼承關(guān)系更多的對(duì)象。更多的對(duì)象會(huì)使得查錯(cuò)變得困難,特別是這些對(duì)象看上去都很相像。

與橋接模式的區(qū)別

之前總結(jié)了C++設(shè)計(jì)模式——橋接模式;你會(huì)發(fā)現(xiàn),二者都是為了防止過(guò)度的繼承,從而造成子類泛濫的情況。那么二者之間的主要區(qū)別是什么呢?橋接模式的定義是將抽象化與實(shí)現(xiàn)化分離(用組合的方式而不是繼承的方式),使得兩者可以獨(dú)立變化??梢詼p少派生類的增長(zhǎng)。如果光從這一點(diǎn)來(lái)看的話,和裝飾者差不多,但兩者還是有一些比較重要的區(qū)別:

1.橋接模式中所說(shuō)的分離,其實(shí)是指將結(jié)構(gòu)與實(shí)現(xiàn)分離(當(dāng)結(jié)構(gòu)和實(shí)現(xiàn)有可能發(fā)生變化時(shí))或?qū)傩耘c基于屬性的行為進(jìn)行分離;而裝飾者只是對(duì)基于屬性的行為進(jìn)行封閉成獨(dú)立的類,從而達(dá)到對(duì)其進(jìn)行裝飾,也就是擴(kuò)展。比如:異常類和異常處理類之間就可以使用橋接模式來(lái)實(shí)現(xiàn)完成,而不能使用裝飾模式來(lái)進(jìn)行設(shè)計(jì);如果對(duì)于異常的處理需要進(jìn)行擴(kuò)展時(shí),我們又可以對(duì)異常處理類添加Decorator,從而添加處理的裝飾,達(dá)到異常處理的擴(kuò)展,這就是一個(gè)橋接模式與裝飾模式的搭配;

2.橋接中的行為是橫向的行為,行為彼此之間無(wú)關(guān)聯(lián),注意這里的行為之間是沒(méi)有關(guān)聯(lián)的,就比如異常和異常處理之間是沒(méi)有行為關(guān)聯(lián)的一樣;而裝飾者模式中的行為具有可疊加性,其表現(xiàn)出來(lái)的結(jié)果是一個(gè)整體,一個(gè)各個(gè)行為組合后的一個(gè)結(jié)果。

總結(jié)

裝飾模式重點(diǎn)在裝飾,對(duì)核心功能的裝飾作用;將繼承中對(duì)子類的擴(kuò)展轉(zhuǎn)化為功能類的組合,從而將需要對(duì)子類的擴(kuò)展轉(zhuǎn)嫁給用戶去進(jìn)行調(diào)用組合,用戶如何組合由用戶去決定。我在學(xué)習(xí)裝飾模式時(shí),就是重點(diǎn)分析了“裝飾”這個(gè)詞,我們都知道,裝飾是在一個(gè)核心功能上添加一些附屬功能,從而讓核心功能發(fā)揮更大的作用,但是最終它的核心功能是不能丟失的。這就好比我們進(jìn)行windows shell開(kāi)發(fā)時(shí),我們是對(duì)windows的這層殼進(jìn)行了功能的裝飾,從而實(shí)現(xiàn)了我們需要的一些裝飾功能,但是最終的功能還是由windows shell去完成。這就好比,我們的裝飾就是給核心功能添加了一層外衣,讓它看起來(lái)更漂亮和完美。

相關(guān)文章

  • 漫畫講解C語(yǔ)言中最近公共祖先的三種類型

    漫畫講解C語(yǔ)言中最近公共祖先的三種類型

    這篇文章主要總結(jié)了使用C語(yǔ)言查找最近公共祖先的三種方法類型,用漫畫的方式講解原理定義,看上去更生動(dòng)形象,幫助你更好的理解透徹,快來(lái)跟著本文往下看吧
    2021-11-11
  • C語(yǔ)言 格式化讀寫文件詳解

    C語(yǔ)言 格式化讀寫文件詳解

    本文主要介紹C語(yǔ)言 格式化讀寫文件,這里提供了關(guān)于格式化讀寫文件的基本資料及實(shí)現(xiàn)示例代碼,有興趣的小伙伴可以參考下,以便理解學(xué)習(xí)
    2016-08-08
  • C語(yǔ)言快速掌握位段使用

    C語(yǔ)言快速掌握位段使用

    位段位段的聲明和結(jié)構(gòu)是類似的,但是也會(huì)有所不同,此篇文章將帶你了解位段是什么已以及位段的使用和位段的特性,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-09-09
  • 詳解Linux的SOCKET編程

    詳解Linux的SOCKET編程

    這篇文章主要介紹了Linux的SOCKET編程,并且進(jìn)行了實(shí)例講解,需要的朋友可以參考下
    2015-08-08
  • C語(yǔ)言實(shí)現(xiàn)將彩色bmp圖像轉(zhuǎn)化為灰圖、灰度圖像反色

    C語(yǔ)言實(shí)現(xiàn)將彩色bmp圖像轉(zhuǎn)化為灰圖、灰度圖像反色

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)將彩色bmp圖像轉(zhuǎn)化為灰圖、灰度圖像反色,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 文件編譯時(shí)出現(xiàn)multiple definition of ''xxxxxx''的具體解決方法

    文件編譯時(shí)出現(xiàn)multiple definition of ''xxxxxx''的具體解決方法

    以下是對(duì)文件編譯時(shí)出現(xiàn)multiple definition of 'xxxxxx'的解決方法進(jìn)行了詳細(xì)的分析介紹,如也遇到此問(wèn)題的朋友們可以過(guò)來(lái)參考下
    2013-07-07
  • C++ 再識(shí)類和對(duì)象

    C++ 再識(shí)類和對(duì)象

    類是創(chuàng)建對(duì)象的模板,一個(gè)類可以創(chuàng)建多個(gè)對(duì)象,每個(gè)對(duì)象都是類類型的一個(gè)變量;創(chuàng)建對(duì)象的過(guò)程也叫類的實(shí)例化。每個(gè)對(duì)象都是類的一個(gè)具體實(shí)例(Instance),擁有類的成員變量和成員函數(shù)
    2021-10-10
  • C語(yǔ)言中關(guān)于樹(shù)和二叉樹(shù)的相關(guān)概念

    C語(yǔ)言中關(guān)于樹(shù)和二叉樹(shù)的相關(guān)概念

    這篇文章主要介紹了Java?數(shù)據(jù)結(jié)構(gòu)之樹(shù)和二叉樹(shù)相關(guān)資料,文中通過(guò)示例代碼和一些相關(guān)題目來(lái)做介紹,非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • 基于C語(yǔ)言實(shí)現(xiàn)見(jiàn)縫插針游戲的示例代碼

    基于C語(yǔ)言實(shí)現(xiàn)見(jiàn)縫插針游戲的示例代碼

    見(jiàn)縫插針游戲就是使用鼠標(biāo)左鍵點(diǎn)擊發(fā)射針,當(dāng)兩個(gè)針的夾角小于一定限制時(shí),游戲結(jié)束。本文將用C語(yǔ)言實(shí)現(xiàn)這一有趣游戲,感興趣的可以了解一下
    2022-11-11
  • 淺析操作系統(tǒng)中的虛擬地址與物理地址

    淺析操作系統(tǒng)中的虛擬地址與物理地址

    本文主要介紹了操作系統(tǒng)中的虛擬地址與物理地址。在早期的計(jì)算機(jī)中,要運(yùn)行一個(gè)程序,會(huì)把這些程序全都裝入內(nèi)存,程序都是直接運(yùn)行在內(nèi)存上的,也就是說(shuō)程序中訪問(wèn)的內(nèi)存地址都是實(shí)際的物理內(nèi)存地址。那當(dāng)程序同時(shí)運(yùn)行多個(gè)程序時(shí),操作系統(tǒng)是如何為這些程序分配內(nèi)存的呢
    2021-06-06

最新評(píng)論