python開發中常用的設計模式(裝飾者模式)

原文取自大話設計模式,這裏將其改爲python代碼進行實現

 需求:現有一個用戶,實現其穿衣服、穿褲子、打領帶的功能,並保證其擴展性。



# 菜鳥代碼

class Person():
    name = ""

    def __init__(self, name):
        self.name = name

    def WearTShirts(self):
        print("大T恤")

    def WearBigTrouse(self):
        print("垮褲")

    def WearSneakers(self):
        print("破球鞋")

    def WearSuit(self):
        print("西裝")

    def WearTie(self):
        print("領帶")

    def WearLeatherShoes(self):
        print("皮鞋")

    def Show(self):
        print("我的裝扮是:"+self.name)


if __name__ == '__main__':
    print("第一種裝扮:")
    person1=Person("程序猿")
    person1.WearBigTrouse()
    person1.WearLeatherShoes()
    person1.WearSneakers()
    person1.Show()

    print("第二種裝扮:")
    person2=Person("程序猿")
    person2.WearSuit()
    person2.WearTie()
    person2.WearTShirts()
    person2.Show()

# 上述代碼擴展性很差,不遵守開放封閉原則

上面的代碼完全沒有擴展性,彷彿就是針對某個特定用戶實現一樣。

如若添加其它的衣服種類,或其他的用戶,則上面的代碼就要over了。

需求大量改變時。。。更。。。

 

對上面的代碼進行改進:


import abc


class Person():
    name=""
    def __init__(self,name):
        self.name=name
    def show(self):
        print("裝扮的:"+self.name)

class Finery():
    @abc.abstractmethod
    def show(self):
        pass

class Thirts(Finery):
    def show(self):
        print("大T恤")


class WearBigTrouse(Finery):
    def show(self):
        print("垮褲")

class WearSneakers(Finery):
    def show(self):
        print("破球鞋")

class WearSuit(Finery):
    def show(self):
        print("西裝")

class WearTie(Finery):
    def show(self):
        print("領帶")

class WearLeatherShoes(Finery):
    def show(self):
        print("皮鞋")

if __name__ == '__main__':

    print("第一種裝扮:")
    person=Person("程序猿")
    dtx=Thirts()
    kk=WearBigTrouse()
    pqx=WearSneakers()
    dtx.show()
    kk.show()
    pqx.show()
    person.show()


    print("第二種裝扮:")
    person=Person("程序猿")
    dtx=WearSuit()
    kk=WearLeatherShoes()
    pqx=WearTie()
    dtx.show()
    kk.show()
    pqx.show()
    person.show()

# 上面的代碼將各種服裝進行了擴展,但是調用起來還是方便

改進的代碼雖然對衣服類進行了抽象封裝,具有了擴展性,但是調用起來非常麻煩。

比如說:當上面的【程序猿】穿任意一個衣服時,都要將這個【裸體】【程序猿】進行傳遞,沒有串起來。

即【程序猿】穿了【上衣】後、常規來講肯定是將【穿過上衣的程序猿】傳遞給【下一個衣服】。

而不是將【裸體】的【程序猿】進行傳遞。

即沒有按需進行順序控制。

 

對上述的代碼再次改版,用裝飾者模式進行實現:

裝飾者模式:動態的給對象添加一些額外的職責!


import abc

# 定義一個對象的接口,動態的給對象添加職責
class Component():
    @abc.abstractmethod
    def Operation(self):
        pass


# 具體的裝飾對象,給具體的對象添加職責或功能
class ConcreteComPonent(Component):

    def __init__(self):
        print("我是小明,我是一個對象!!")

    def Operation(self):
        print("我要開始穿衣服了.....")


# 裝飾抽象類,從外類來擴展對象的接口的方法,這個類就是用擴展對象接口的
# 這個類主要用來服務具體的裝飾對象的,即保留服務對象
# 其中component指的就是服務對象-小明

class Decorator(Component):
    component=None

    def __init__(self):
        print("創建了裝飾對象")

    def setComponent(self,component):
        self.component=component


    def Operation(self):
        if self.component!=None:
            self.component.Operation()


# 裝飾對象A
class ConcreteDecoratorA(Decorator):

    addedState="A"
    def __init__(self):
        print("創建了裝飾A對象")


    def Operation(self):
        super().Operation()
        self.addedState="修改裝飾對象A的屬性爲:AAAAA"
        print("穿上衣")

# 裝飾對象B
class ConcreteDecoratorB(Decorator):
    addedState="B"

    def __init__(self):
        print("創建了裝飾B對象")

    def Operation(self):
        super().Operation()
        self.addedState="修改裝飾對象B的屬性爲:BBBBB"
        print("穿褲子")

    # 裝飾對象B獨有的操作
    def AddedBehavior(self):
        print("開始喫飯")


if __name__ == '__main__':
    # 具體的裝飾對象
    c=ConcreteComPonent()
    # 創建裝飾對象A
    a1=ConcreteDecoratorA()
    # 創建裝飾對象B
    b1=ConcreteDecoratorB()

    # 將具體對象小明傳給裝飾對象A,這句話執行後裝飾對象A中包含了小明,即A(小明)
    a1.setComponent(c)

    # 裝飾對象A 傳給裝飾對象B,這句話執行後,裝飾對象B中包含了A,即B(A(小明))
    b1.setComponent(a1)

    # 開始執行穿衣操作
    b1.Operation()

    b1.AddedBehavior()

這個模式的精髓在於將【對象】裝進A、將【A】裝進【B】,最後調用【B】的獨有方法(等同於一條線將所有事情串起來)

注:也可以在A中創建A獨有的方法並且調用,然後再傳給B

其中:

調用【B】的方法時、會獲取到【A】(因爲B對象的component這時候存儲的時A)

注:對象【A】是通過Super()方法獲取到的,沒有這個方法則獲取不到

獲取到【A】後,調用了其Operation()方法,然後通過這個方法得到了【小明】,與上述同理,也是通過Super()方法獲取到的小明,然後A再調用自己的方法!!!

運行結果如下:

調用的時候有點像遞歸,即一層一層網上走,走到最頂層是,開始一層一層往下執行。

稍微有點難理解,但明白了還是很有幫助的。

一定要注意Super()方法,整個代碼都圍繞着這個方法在轉!!

一定要注意Super()方法,整個代碼都圍繞着這個方法在轉!!

一定要注意Super()方法,整個代碼都圍繞着這個方法在轉!!

如有錯誤,敬請指正!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章