乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      從Adapter模式到Decorator模式

       ljjzlm 2006-08-04
       

      從Adapter模式到Decorator模式

      作者/來(lái)源: Bruce Zhang

       

      一、考察對(duì)象的Adapter模式

      從上文看到,經(jīng)過(guò)引入Adapter模式,原有的結(jié)構(gòu)得到了改進(jìn)。但我們還需要從客戶的角度分析程序,使結(jié)構(gòu)更加地合理。(這里,我們僅限于考察對(duì)象的Adapter模式。類的Adapter模式不存在下述問(wèn)題。這也印證了一個(gè)事實(shí),就是:對(duì)象的Adapter模式和類的Adapter模式各有優(yōu)勢(shì),也各有缺點(diǎn),設(shè)計(jì)時(shí)應(yīng)根據(jù)實(shí)際情況考察。)

      1、擴(kuò)展的功能是否合理?

      假設(shè)用戶希望調(diào)用VedioMedia同時(shí)具有Play()和Resize()功能。從前面的描述來(lái)看,客戶只需要實(shí)例化VedioAdapter類對(duì)象,就可以調(diào)用了??磥?lái)結(jié)構(gòu)是正確的。

      2、類型的擴(kuò)展是否合理?

      從目前的需求來(lái)看,要調(diào)用RM和MPEG類型的對(duì)象,沒(méi)有任何問(wèn)題。但是正如呂震宇所說(shuō),在VedioMedia類的Resize()方法中有一股腐化的味道。壞味道的根源就是if 條件語(yǔ)句。如果要增加新的視頻類型,就需要修改Resize()方法了。這是一個(gè)設(shè)計(jì)的權(quán)衡。其實(shí)這個(gè)味道雖然夠壞,但好處是簡(jiǎn)單,也不用更多的對(duì)象;但耦合性比較差。

      如果我們的目標(biāo)是希望更好的架構(gòu)以支持耦合的松散,目前的結(jié)構(gòu)就需要微調(diào)了。調(diào)整后的類圖如下: 

      這樣需要改變VedioAdapter類的代碼:

      public

       

      abstract

       

      class VedioAdapter:IVedioScreen

      {

       

      protected vedioMedia _vedio;

       

       

      public VedioAdapter(vedioMedia vedio)

       

      {

        _vedio = vedio;

       }

       

      public

       

      void Play()

       

      {

        _vedio.Play();  

       }

       

      public

       

      abstract

       

      void Resize();

      }

      然后實(shí)現(xiàn)RMAdapter和MPEGAdatper:

      public

       

      class RMAdapter:VedioAdapter

      {

       

      public RMAdapter(VedioMedia vedio):base(vedio){}

       

       

      public

       

      override

       

      void Resize()

       

      {

        MessageBox.Show(”Change the RM screen’s size.”);

       }

      }

      (MPEGAdapter的代碼省略)

      這樣一改,要擴(kuò)展就容易了,不過(guò)比之以前設(shè)計(jì)要復(fù)雜些,希望不會(huì)有人說(shuō)我過(guò)度設(shè)計(jì)。如果要考慮正確性的話,RMAdapter的構(gòu)造函數(shù)還需要考慮異常情況。由于構(gòu)造函數(shù)的參數(shù)為VedioMedia類型,因此,客戶在調(diào)用時(shí)可能會(huì)傳入MPEG類型,此時(shí)RMAdapter類型的Play()行為就會(huì)發(fā)生改變。這也是和Decorator最大的不同,就是我們必須限制對(duì)象的Play()方法不能做任何改變。

      public RMAdapter(VedioMedia vedio):base(vedio)

      {

       

      if (!(vedio is RM))

        throw

       

      new Exception(”VedioMedia object

       

      is not correct!”);

      }

      3、是否與原有客戶系統(tǒng)兼容?

      如果在原有的客戶系統(tǒng)中提供了如下的類及方法:

      public

       

      class MediaFile

      {

       

      public

       

      static

       

      void Play(IMedia media)

       

      {

        media.Play();

       }

      }

      那么客戶如下的調(diào)用是沒(méi)有任何問(wèn)題的:

      MediaFile.Play(new RM());

      然而,當(dāng)客戶要使用新的Adapter對(duì)象呢?例如:

      MediaFile.Play(new RMAdapter());

      顯然是有問(wèn)題了,因?yàn)镽MAdpater類沒(méi)有實(shí)現(xiàn)IMedia接口,且RMAdpater類的Play()方法和IMedia接口的Play()方法在性質(zhì)上也是有區(qū)別的。此時(shí),采用原有的設(shè)計(jì)就不正確了。改進(jìn)的方法很簡(jiǎn)單,就是讓VedioAdapter類實(shí)現(xiàn)IMedia接口就可以了:

      public abstract class VedioAdapter:IVedioScreen,IMedia

      {

       ……

      }

      根據(jù)呂震宇所說(shuō),當(dāng)VedioAdapter類實(shí)現(xiàn)IMedia接口時(shí),言外之意就是該Adapter也適合AudioMedia類型了。是否如此呢?可以說(shuō)是一半對(duì),一半不對(duì)。對(duì)的原因,是由于AudioMedia類也實(shí)現(xiàn)了IMedia接口;但別忘了,我們適配的并非類,而是對(duì)象,也就是在VedioAdapter中傳遞進(jìn)來(lái)的VedioMedia對(duì)象。(如果我們將傳遞進(jìn)來(lái)的對(duì)象擴(kuò)展為IMedia,那就糟糕了。震宇兄的結(jié)論就完全成立了。)同時(shí),我們?cè)跇?gòu)造函數(shù)的異常處理,也保證了AudioMedia類型對(duì)于VedioAdapter是非法的。

      寫到這里,我覺(jué)得本文已經(jīng)超出了原來(lái)的設(shè)想,有些研究的味道了。嗯,還算不錯(cuò)。那么就繼續(xù)研究下去吧。

      二、引入Decorator模式

      按照最初的需求,我引入Decorator模式試一試。最初的需求是,需要為RM和MPEG類在不改變?cè)写a的情況下,添加Resize()方法,而其原來(lái)的Play()方法不變。調(diào)整設(shè)計(jì)類圖:

      上圖的橙紅色區(qū)域?yàn)镈ecorator模式的主體,至于IVedioScreen接口,僅僅是為VedioDecorator增加Resize()方法而引入的,其本身與Decorator無(wú)關(guān),除非我要實(shí)現(xiàn)的Decorator功能,通過(guò)該接口來(lái)實(shí)現(xiàn)。代碼如下:

      public

       

      abstract

       

      class VedioDecorator:VedioMedia,IVedioScreen

      {

       

      private VedioMedia _vedio;

       

       

      public VedioAdapter(vedioMedia vedio)

       

      {

        _vedio = vedio;

       }

       

      public VedioMedia Vedio

       

      {

        get

       

      {return _vedio;}

       }

       

      public

       

      abstract

       

      void Resize();

      }

      注意看,與前面Adapter模式的VedioAdapter類比較,除增加了對(duì)VedioMedia的派生外,還減少了Play(),因?yàn)樵摲椒ㄒ呀?jīng)從VedioMedia類中派生獲得。這樣的話,RMDecorator和MPEGDecorator,也需要做相應(yīng)的改變:

      public

       

      class RMDecorator:VedioDecorator

      {

       

      public RMDecorator (VedioMedia vedio):base(vedio)

       

      {

        if (!(vedio is RM))

         throw

       

      new Exception(”VedioMedia object

       

      is not correct!”);

       }

       

       

      public

       

      override

       

      void Play()

       

      {

        Vedio.Play();

       }

       

      public

       

      override

       

      void Resize()

       

      {

        MessageBox.Show(”Change the RM screen’s size.”);

       }

      }

      到這個(gè)時(shí)候,我忽然覺(jué)得引入Decorator模式,已經(jīng)有些力不從心了。為什么呢?最大的障礙就是我們的需求不能更改VedioMedia類型Play()方法的既有行為。這個(gè)時(shí)候,所謂的Decorator已經(jīng)失去了原來(lái)的意義。其實(shí)我覺(jué)得,此時(shí)的設(shè)計(jì),應(yīng)該是結(jié)合了Adapter模式與Decorator模式而衍生出的新的結(jié)構(gòu)。

      那么,我為什么還要在本文提出引入Decorator模式呢。這來(lái)源我對(duì)于設(shè)計(jì)模式一向的觀點(diǎn):不要為了模式而模式!GOF的23種模式,并非茴香豆的“茴”字,我也并非孔乙己,要你回答“茴”字的寫法,卻忽略了使用設(shè)計(jì)模式的真正精神。設(shè)計(jì)模式歸根結(jié)底是拿來(lái)用的。只要符合你的要求,各種模式隨你怎么變都可以。因此,不管是前文所述的Adapter模式,還是改進(jìn)后的Adapter模式,或者引入的Decorator模式,其中的變化是靈活的,選擇權(quán)最終還是你。

      三、正宗的Decorator模式

      不過(guò),我還是很有興趣繼續(xù)探討下去,仍然借助媒體播放這個(gè)例子,來(lái)談一談Decorator模式的一般應(yīng)用?,F(xiàn)在我們要求RM和MPEG媒體在播放前,首先要顯示媒體文件的版權(quán)信息。請(qǐng)注意,這個(gè)需求,并非是為RM等媒體增加ShowCopyright()方法,而Play()方法保持不變。恰恰相反,新的需求裝飾了Play()的行為,它要求Play()的同時(shí)能夠支持ShowCopyright的功能。類圖如下:

      在這里,VedioDecorator是裝飾類的抽象類,而CopyRightVedioDecorator類則具體裝飾了Play()的功能。

      public

       

      abstract

       

      class VedioDecorator:VedioMedia

      {

       

      private VedioMedia _vedio;

       

       

      public VedioAdapter(vedioMedia vedio)

       

      {

        _vedio = vedio;

       }

       

      public VedioMedia Vedio

       

      {

        get

       

      {return _vedio;}

       }

      }

      然后實(shí)現(xiàn)CopyRightVedioDecorator類,為Play()方法裝飾顯示版權(quán)信息的功能:

      public

       

      class CopyRightVedioDecorator:VedioDecorator

      {

       

      private CopyRight _copyRightMark;

       

       

      public CopyRight CopyRightMark

       

      {

        get

       

      {return _copyRightMark;}

        set

       

      {_copyRightMark = value;}

       }

       

      public

       

      override

       

      void Play()

       

      {

        _copyRightMark.ShowCopyRight();

        Vedio.Play();

       }

      }

      我們還可以繼續(xù)裝飾VedioMedia的Play行為,例如,要求在播放媒體文件之前,必須放一段廣告,那么我們可以繼續(xù)提供一個(gè)AdvertisementVedioDecorator裝飾類。道理與上一樣,不再贅述。

      通過(guò)本例,我們可以看到Decorator模式與對(duì)象的Adapter模式的區(qū)別。

      實(shí)現(xiàn)的區(qū)別:

      1、Decorator抽象類應(yīng)繼承要裝飾的類,同時(shí)又聚合該類的實(shí)例對(duì)象;而對(duì)象的Adapter模式則只聚合,不繼承;

      2、Decor模式并沒(méi)有引入新的接口,除非要裝飾的行為需要使用該接口;而對(duì)象的Adapter模式則引入了新的接口,以此來(lái)裝配原有的對(duì)象,使其具有了新接口的方法;

      因此,適用的場(chǎng)景也就有所不同:

      1、Decorator模式如其名,一般并不提供新的行為,而是在原有的行為上進(jìn)行補(bǔ)充,即裝飾的含義。

      2、Adapter模式則是為對(duì)象引入新的行為,使其匹配新的接口,即為適配的意義所在。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多