原文取自大話設計模式,這裏將其改爲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()方法,整個代碼都圍繞着這個方法在轉!!!
如有錯誤,敬請指正!!!