成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

python設(shè)計(jì)模式-裝飾器模式

Yuqi / 1160人閱讀

摘要:這種模式我們稱之為裝飾器模式。因?yàn)檠b飾器模式是在給對(duì)象增加責(zé)任。以下情況適合使用裝飾器模式在不影響其他對(duì)象的情況下,以動(dòng)態(tài)透明的方式給單個(gè)對(duì)象添加職責(zé)。

前言

本篇的裝飾器模式不是講解的python中的語(yǔ)法糖 @ 這個(gè)裝飾器。而是講解設(shè)計(jì)模式中的裝飾器模式。網(wǎng)上很多的實(shí)現(xiàn)都是基于java和c++的。本文則使用python來(lái)實(shí)現(xiàn),其中有些實(shí)現(xiàn)可能在python并不需要那樣來(lái)寫的,但是思路都是一樣的。關(guān)于python @ 裝飾器的使用我之后會(huì)再寫一篇文章來(lái)介紹。

產(chǎn)生裝飾器模式的動(dòng)機(jī)是什么?

大家知道我們有的時(shí)候總是需要給給一個(gè)類或者一個(gè)對(duì)象增加一些行為。一般情況下使用繼承和關(guān)聯(lián)兩種方式來(lái)實(shí)現(xiàn)。其中使用關(guān)聯(lián)這種方式來(lái)實(shí)現(xiàn)并符合一定的設(shè)計(jì)規(guī)范的我們稱之為裝飾器模式。接下來(lái)我們首先會(huì)先介紹一下這兩種方法,然后用python代碼來(lái)分別實(shí)現(xiàn)這兩種方法并比較他們之間的差異。

繼承方式

一般情況下我們都是通過(guò)繼承來(lái)給一個(gè)或一群類來(lái)添加方法,通過(guò)繼承使子類獲得了父類的行為。雖然繼承是一種適用廣泛的方法,但是繼承是一種靜態(tài)行為,在代碼編寫階段就已經(jīng)固定,無(wú)法動(dòng)態(tài)的控制一個(gè)類增加行為的種類和時(shí)間。

關(guān)聯(lián)關(guān)系

我們通過(guò)將一個(gè)A對(duì)象嵌入另一個(gè)B對(duì)象里面,及將一個(gè)B對(duì)象里面的屬性的值設(shè)置為A對(duì)象。通過(guò)在調(diào)用A對(duì)象的動(dòng)作前后添加行為來(lái)給A對(duì)象增加功能。這種模式我們稱之為裝飾器模式。

“裝飾模式以對(duì)客戶透明的方式動(dòng)態(tài)地給一個(gè)對(duì)象附加上更多的責(zé)任,換言之,客戶端并不會(huì)覺(jué)得對(duì)象在裝飾前和裝飾后有什么不同。裝飾模式可以在不需要?jiǎng)?chuàng)造更多子類的情況下,將對(duì)象的功能加以擴(kuò)展。這就是裝飾模式的模式動(dòng)機(jī)?!盵1]

因?yàn)檠b飾器模式是在給對(duì)象增加責(zé)任。所以裝飾器模式為對(duì)象結(jié)構(gòu)型設(shè)計(jì)模式(對(duì)象是因?yàn)槠涫墙o對(duì)象而不是類增加責(zé)任,結(jié)構(gòu)型模式就是描述如何將類或者對(duì)象結(jié)合在一起形成更大的結(jié)構(gòu),就像搭積木,可以通過(guò)簡(jiǎn)單積木的組合形成復(fù)雜的、功能更為強(qiáng)大的結(jié)構(gòu))。

實(shí)例講解 代碼描述

一個(gè)飲料店里面賣茶和咖啡。 并且有冰塊,糖和牛奶三種輔料可以添加。 我們可以計(jì)算出一共有14中組合產(chǎn)品。并且每增加一種飲料就要增加7種組合產(chǎn)品。

繼承方式 UML類圖

代碼
class DrinkComponent(object):
    def get_price(self):
        pass

    def get_name(self):
        pass


class TeaConcreteComponent(DrinkComponent):
    def __init__(self):
        self.__name = "Tea"
        self.__price = 2

    def get_price(self):
        return self.__price

    def get_name(self):
        return self.__name


class CoffeeConcreteComponent(DrinkComponent):
    def __init__(self):
        self.__name = "coffee"
        self.__price = 3

    def get_price(self):
        return self.__price

    def get_name(self):
        return self.__name


class IngredientsComponent(object):
    pass


class IceConcreteComponent(IngredientsComponent):
    def add_ice_price(self):
        return 0.3

    def add_ice_name(self):
        return "+Ice"


class SugerConcreteComponent(IngredientsComponent):
    def add_suger_price(self):
        return 0.5

    def add_suger_name(self):
        return "+Suger"


class MilkConcreteComponent(IngredientsComponent):
    def add_milk_price(self):
        return 1

    def add_milk_name(self):
        return "+Milk"


class Tea_Milk(TeaConcreteComponent, MilkConcreteComponent):
    def get_price(self):
        return TeaConcreteComponent.get_price(self) + MilkConcreteComponent.add_milk_price(self)

    def get_name(self):
        return TeaConcreteComponent.get_name(self) + MilkConcreteComponent.add_milk_name(self)


class Tea_Milk_Ice(TeaConcreteComponent, MilkConcreteComponent, IceConcreteComponent):
    def get_price(self):
        return TeaConcreteComponent.get_price(self) + MilkConcreteComponent.add_milk_price(self) 
               + IceConcreteComponent.add_ice_price(self)

    def get_name(self):
        return TeaConcreteComponent.get_name(self) + MilkConcreteComponent.add_milk_name(self)
               + IceConcreteComponent.add_ice_name(self)

if __name__ == "__main__":
    tea_milk = Tea_Milk()
    print tea_milk.get_name()
    print tea_milk.get_price()

    tea_milk_ice = Tea_Milk_Ice()
    print tea_milk_ice.get_name()
    print tea_milk_ice.get_price()
說(shuō)明

從圖和代碼中看首先我們定義了DrinkComponent和IngredientsComponent即飲料和配料兩個(gè)抽象類,并分別實(shí)現(xiàn)了具體的構(gòu)建類。當(dāng)我們要產(chǎn)生一個(gè)產(chǎn)品的時(shí)候。通過(guò)繼承不同的具體構(gòu)建類來(lái)實(shí)現(xiàn)。比如加冰加牛奶的茶。我們通過(guò)繼承茶、牛奶和冰塊三個(gè)類來(lái)實(shí)現(xiàn)??梢钥闯鋈绻獙?shí)現(xiàn)所有的類那么我們需要14個(gè)子類來(lái)完成。支持多繼承的語(yǔ)言才能這樣實(shí)現(xiàn)如果是單繼承的語(yǔ)言則需要通過(guò)多級(jí)繼承來(lái)完成。不僅冗余度增加而且復(fù)雜的多級(jí)繼承關(guān)系是后期維護(hù)的淚。

關(guān)聯(lián)方式 UML類圖

代碼
class DrinkComponent(object):
    def get_price(self):
        pass

    def get_name(self):
        pass


class TeaConcreteComponent(DrinkComponent):
    def __init__(self):
        self.__name = "Tea"
        self.__price = 2

    def get_price(self):
        return self.__price

    def get_name(self):
        return self.__name


class CoffeeConcreteComponent(DrinkComponent):
    def __init__(self):
        self.__name = "coffee"
        self.__price = 3

    def get_price(self):
        return self.__price

    def get_name(self):
        return self.__name


class IngredientsDecorator(DrinkComponent):
    def __init__(self, drink_component):
        self.drink_component = drink_component

    def get_price(self):
        pass

    def get_name(self):
        pass


class IceConcreteDecorator(IngredientsDecorator):
    def get_price(self):
        return self.drink_component.get_price() + self.add_ice_price()

    def add_ice_price(self):
        return 0.3

    def get_name(self):
        return self.drink_component.get_name() + self.add_ice_name()

    def add_ice_name(self):
        return "+Ice"


class SugerConcreteDecorator(IngredientsDecorator):
    def get_price(self):
        return self.drink_component.get_price() + self.add_suger_price()

    def add_suger_price(self):
        return 0.5

    def get_name(self):
        return self.drink_component.get_name() + self.add_suger_name()

    def add_suger_name(self):
        return "+Suger"


class MilkConcreteDecorator(IngredientsDecorator):
    def get_price(self):
        return self.drink_component.get_price() + self.add_milk_price()

    def add_milk_price(self):
        return 1

    def get_name(self):
        return self.drink_component.get_name() + self.add_milk_name()

    def add_milk_name(self):
        return "+Milk"

if __name__ == "__main__":
    tea_milk = MilkConcreteDecorator(TeaConcreteComponent())
    print tea_milk.get_name()
    print tea_milk.get_price()

    tea_milk_ice = IceConcreteDecorator(MilkConcreteDecorator(TeaConcreteComponent()))
    print tea_milk_ice.get_name()
    print tea_milk_ice.get_price()
說(shuō)明

DrinkComponent 是抽象構(gòu)件類,它是具體構(gòu)建類(*ConcreteComponent)和抽象裝飾器類(IngredientsDecorator)的父類,主要定義了具體構(gòu)建類的業(yè)務(wù)方法。以及讓我們?cè)谡{(diào)用的時(shí)候可以統(tǒng)一的處理裝飾前和裝飾后的對(duì)象。方便我們使用裝飾器類裝飾一個(gè)已經(jīng)被裝飾的具體構(gòu)建如加糖(加冰(咖啡))。在關(guān)聯(lián)關(guān)系中我們主要說(shuō)一下這個(gè)部分。

這是一個(gè)關(guān)聯(lián)聚合關(guān)系。表示IngredientsDecorator是知道DrinkComponent類的存在的呢。這個(gè)大家可以這樣理解。你在實(shí)現(xiàn)Concretecomponet的時(shí)候是不需要考慮IngredinetsDecorator的存在,因?yàn)槟悴粫?huì)調(diào)用它的,也不繼承它,也不知道你會(huì)被它調(diào)用。但是在設(shè)計(jì)實(shí)現(xiàn)ConcreteDecorator的時(shí)候你會(huì)在其屬性中保持一個(gè)對(duì)DrinkComponet類型的類的引用。并且你會(huì)調(diào)用她的方法。這樣你就要知道DrinkCompoent這個(gè)類里面都有什么方法及要知道DrinkComponent類的存在。在另一種設(shè)計(jì)模式橋接模式這種關(guān)系正好是相反的。我之后再來(lái)寫一篇關(guān)于橋接模式的介紹。

我們?cè)诖a中可以看到在IngredientsDecorator中也有g(shù)et_price 和 get_name兩種方法。這是為了保證在ConcreteComponent在被裝飾器后還是可以像沒(méi)有被裝飾那樣被調(diào)喲個(gè)。并且我們可以在調(diào)用的上面和下面添加功能以實(shí)現(xiàn)功能的增強(qiáng)。比如我們?cè)诖a中是這樣寫的

    def get_price(self):
        return self.drink_component.get_price() + self.add_milk_price()

我們也可以將其改寫為這樣

    def get_price(self):
        print "add Milk"
        price = self.drink_component.get_price()
        new_price = price + self.add_milk_price()
        return new_price

我們?cè)谡{(diào)用被修飾的類的前面增加了一個(gè)功能打印 "add milk"這件事,并在獲取了裝飾的產(chǎn)品價(jià)格后給架構(gòu)增加了一個(gè)牛奶的價(jià)格并將其返回。

總結(jié)

通過(guò)裝飾模式來(lái)擴(kuò)展對(duì)象的功能比繼承模式更靈活。構(gòu)建和裝飾器可以獨(dú)立擴(kuò)展,新增功能不需要添加大量的子類。但是裝飾模式也產(chǎn)生了許多小對(duì)象,增加了排錯(cuò)的難度。

以下情況適合使用裝飾器模式:

在不影響其他對(duì)象的情況下,以動(dòng)態(tài)、透明的方式給單個(gè)對(duì)象添加職責(zé)。

需要?jiǎng)討B(tài)地給一個(gè)對(duì)象增加功能,這些功能也可以動(dòng)態(tài)地被撤銷。

當(dāng)不能采用繼承的方式對(duì)系統(tǒng)進(jìn)行擴(kuò)充或者采用繼承不利于系統(tǒng)擴(kuò)展和維護(hù)時(shí)。不能采用繼承的情況主要有兩類:第一類是系統(tǒng)中存在大量獨(dú)立的擴(kuò)展,為支持每一種組合將產(chǎn)生大量的子類,使得子類數(shù)目呈爆炸性增長(zhǎng);第二類是因?yàn)轭惗x不能繼承(如final類).[1]

引用[1] http://design-patterns.readth...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/44493.html

相關(guān)文章

  • Python裝飾vs裝飾模式

    摘要:希望引以為戒鄭傳裝飾模式如果你了解,你肯定聽(tīng)過(guò)裝飾器模式。在面向?qū)ο笾校b飾模式指動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加一些功能來(lái)說(shuō),裝飾模式比生成子類更為靈活。 漫談 如果作為一個(gè)Python入門,不了解Python裝飾器也沒(méi)什么,但是如果作為一個(gè)中級(jí)Python開發(fā)人員,如果再不對(duì)python裝飾器熟稔于心的話,那么可能并沒(méi)有量變積累到質(zhì)變。 我以前也看過(guò)很多講python 裝...

    stackvoid 評(píng)論0 收藏0
  • Python裝飾

    摘要:一引用書流暢的書二基本概念問(wèn)題裝飾器是什么解答嚴(yán)格來(lái)說(shuō),裝飾器只是語(yǔ)法糖,裝飾器是可調(diào)用的對(duì)象,可以像常規(guī)的可調(diào)用對(duì)象那樣調(diào)用,特殊的地方是裝飾器的參數(shù)是一個(gè)函數(shù)問(wèn)題裝飾器有什么特性解答裝飾器有個(gè)特性,一是可以把被裝飾的函數(shù)替換成其他函數(shù), 一, 引用 [書] 流暢的Python [書] Effective Python 二, 基本概念 showImg(https://segme...

    aisuhua 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式裝飾模式

    摘要:作者按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用和兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)現(xiàn)方式,但此小冊(cè)只記錄最直截了當(dāng)?shù)膶?shí)現(xiàn)方式原文地址是每天一個(gè)設(shè)計(jì)模式之裝飾者模式歡迎關(guān)注個(gè)人技術(shù)博客。 作者按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript和python兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)現(xiàn)方式,但此小冊(cè)只記錄最直截了當(dāng)?shù)膶?shí)現(xiàn)方式...

    brianway 評(píng)論0 收藏0
  • 每天一個(gè)設(shè)計(jì)模式裝飾模式

    摘要:作者按每天一個(gè)設(shè)計(jì)模式旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用和兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)現(xiàn)方式,但此小冊(cè)只記錄最直截了當(dāng)?shù)膶?shí)現(xiàn)方式原文地址是每天一個(gè)設(shè)計(jì)模式之裝飾者模式歡迎關(guān)注個(gè)人技術(shù)博客。 作者按:《每天一個(gè)設(shè)計(jì)模式》旨在初步領(lǐng)會(huì)設(shè)計(jì)模式的精髓,目前采用javascript和python兩種語(yǔ)言實(shí)現(xiàn)。誠(chéng)然,每種設(shè)計(jì)模式都有多種實(shí)現(xiàn)方式,但此小冊(cè)只記錄最直截了當(dāng)?shù)膶?shí)現(xiàn)方式...

    shleyZ 評(píng)論0 收藏0
  • Python裝飾

    摘要:此篇緊接上篇裝飾器裝飾器模式,上篇主要是簡(jiǎn)述了裝飾器模式,跟的裝飾器。再來(lái)看裝飾器的實(shí)現(xiàn)。這時(shí)步輕松搞定裝飾器中的例子還是精妙的。最近學(xué)數(shù)據(jù)結(jié)構(gòu)與算法,寫些裝飾器用來(lái)看程序執(zhí)行時(shí)間,真是再方便不過(guò)了 此篇緊接上篇 Python裝飾器vs裝飾器模式,上篇主要是簡(jiǎn)述了裝飾器模式,跟Python的裝飾器。 再來(lái)看Python裝飾器的實(shí)現(xiàn)。這里我推薦一篇文章(譯)-12步輕松搞定python裝...

    sunsmell 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<