[Python設計模式] 第6章 衣服搭配系統——裝飾模式
阿新 • • 發佈:2018-07-27
!= orb 定義 use bstr 單獨 name 代碼 服飾
題目
設計一個控制臺程序,可以給人搭配嘻哈風格(T恤,垮褲,運動鞋)或白領風格(西裝,領帶,皮鞋)的衣服並展示,類似QQ秀那樣的。
基礎版本
class Person(): def __init__(self, name): self.name = name def wear_T_shirts(self): print("T恤") def wear_big_trouser(self): print("垮褲") def wear_sneakers(self): print("運動鞋") def wear_suit(self): print("西裝") def wear_tie(self): print("領帶") def wear_leather_shoes(self): print("皮鞋") def show(self): print("裝扮的{}".format(self.name))
客戶端代碼
def main(): hezhang = Person("張賀") print("第一種裝扮") hezhang.wear_T_shirts() hezhang.wear_big_trouser() hezhang.wear_sneakers() hezhang.show() print("第二種裝扮") hezhang.wear_suit() hezhang.wear_tie() hezhang.wear_leather_shoes() hezhang.show() main()
第一種裝扮
T恤
垮褲
運動鞋
裝扮的張賀
第二種裝扮
西裝
領帶
皮鞋
裝扮的張賀
點評
- 僅實現了基本功能
- 如果添加“超人”裝扮,需要如何做?需要在Person類中改代碼;
- 如果Person類除了穿衣服,還要支持吃飯,睡覺等功能,需要如何做?需要在Person類中改代碼;
- 綜上,需要把“服飾”類和“人”類分離。
改進版本1.0——人衣分離
class Person(): def __init__(self, name): self.name = name def show(self): print("裝扮的{}".format(self.name)) from abc import ABCMeta, abstractmethod class Finery(metaclass=ABCMeta): @abstractmethod def show(self): pass class TShirts(Finery): def show(self): print("T恤") class BigTrouser(Finery): def show(self): print("垮褲") class Sneakers(Finery): def show(self): print("運動鞋") class Suit(Finery): def show(self): print("西裝") class Tie(Finery): def show(self): print("領帶") class LeatherShoes(Finery): def show(self): print("皮鞋")
客戶端代碼
def main():
hezhang = Person("張賀")
print("第一種裝扮")
t_shirts = TShirts()
big_trouser = BigTrouser()
sneakers = Sneakers()
t_shirts.show()
big_trouser.show()
sneakers.show()
hezhang.show()
print("第二種裝扮")
suit = Suit()
tie = Tie()
leather_shoes = LeatherShoes()
suit.show()
tie.show()
leather_shoes.show()
hezhang.show()
main()
第一種裝扮
T恤
垮褲
運動鞋
裝扮的張賀
第二種裝扮
西裝
領帶
皮鞋
裝扮的張賀
點評
分析以下代碼:
hezhang = Person("張賀")
t_shirts = TShirts()
big_trouser = BigTrouser()
sneakers = Sneakers()
t_shirts.show()
big_trouser.show()
sneakers.show()
hezhang.show()
用自然語言描述就是:
- 先實例化出
hezhang
這個人類,準確的說,是沒有穿衣服的人類; - 再實例化並穿上出各種衣服,T恤,垮褲,運動鞋等;
- 再展示出來
hezhang
;
但是服飾和人之間好像沒有任何關系,那麽如何用代碼表示:
- 實例化沒穿衣服的人類
- 為沒穿衣服的人類穿上T恤
- 為穿著T恤的人類穿上垮褲
- 為穿著T恤,垮褲的人類穿上運動鞋
這需要用到裝飾模式。
裝飾模式
裝飾模式,為了動態的給一個對象添加一些額外的職責,就增加功能而言,裝飾模式比生成子類更為靈活[DP]。
裝飾模式有以下幾個主要組成部分:
- 組件類Component:定義一個對象接口, 可以給這些對象動態的添加職責;
- 具體組件類ConcretComponent:定義了一個具體對象,也可以給這個對象添加一些職責;
- 裝飾類Decorator:裝飾抽象類,繼承Component,從外類來擴展Component類的功能,對於Component而言,無需知道Decorator的存在;
- 具體裝飾類ConcretDecorator:具體裝飾類,為Component添加職責
用代碼表示:
from abc import ABCMeta, abstractmethod
class Component(metaclass=ABCMeta):
"""
組件類Component:定義一個對象接口, 可以給這些對象動態的添加職責
"""
@abstractmethod
def operation(self):
pass
class ConcreteComponent(Component):
"""
具體組件類ConcretComponent:定義了一個具體對象,也可以給這個對象添加一些職責
"""
def operation(self):
print("具體組件的操作")
class Decorator(Component):
"""
裝飾類Decorator:裝飾抽象類,繼承Component,從外類來擴展Component類的功能,對於Component而言,無需知道Decorator的存在;
"""
def __init__(self):
self.component = None
def set_component(self, component):
self.component = component
def operation(self):
if self.component != None:
self.component.operation()
class ConcreteDecratorA(Decorator):
"""
具體裝飾類ConcretDecorator:具體裝飾類,為Component添加職責
"""
def __init__(self):
self.added_operation = "A:具體裝飾類A獨有操作"
def operation(self):
super().operation()
print(self.added_operation)
print("A:具體裝飾對象A的操作")
class ConcreteDecratorB(Decorator):
"""
具體裝飾類ConcretDecorator:具體裝飾類,為Component添加職責
"""
def __init__(self):
self.added_operation = "B:具體裝飾類B獨有操作"
def operation(self):
super().operation()
print(self.added_operation)
print("B:具體裝飾對象B的操作")
def main():
component = ConcreteComponent()
decorator_a = ConcreteDecratorA()
decorator_b = ConcreteDecratorB()
decorator_a.set_component(component)
decorator_b.set_component(decorator_a)
decorator_b.operation()
main()
具體組件的操作
A:具體裝飾類A獨有操作
A:具體裝飾對象A的操作
B:具體裝飾類B獨有操作
B:具體裝飾對象B的操作
改進版本2.0——裝飾模式
from abc import ABCMeta,abstractmethod
class Person():
"""
人物類(組件類)
"""
def __init__(self, name):
self.name = name
def show(self):
print("裝扮的{}".format(self.name))
class Finery(Person):
"""
服飾類(裝飾類)
"""
def __init__(self):
self.component = None
def decorate(self, component):
self.component = component
def show(self):
if self.component != None:
self.component.show()
class TShirts(Finery):
"""
具體裝飾類
"""
def show(self):
print("T恤")
super().show()
class BigTrouser(Finery):
"""
具體裝飾類
"""
def show(self):
print("垮褲")
super().show()
class Sneakers(Finery):
"""
具體裝飾類
"""
def show(self):
print("運動鞋")
super().show()
class Suit(Finery):
"""
具體裝飾類
"""
def show(self):
print("西裝")
super().show()
class Tie(Finery):
"""
具體裝飾類
"""
def show(self):
print("領帶")
super().show()
class LeatherShoes(Finery):
"""
具體裝飾類
"""
def show(self):
print("皮鞋")
super().show()
客戶端代碼
def main():
hezhang = Person("張賀")
t_shirts = TShirts()
big_trouser = BigTrouser()
sneakers = Sneakers()
t_shirts.decorate(hezhang)
big_trouser.decorate(t_shirts)
sneakers.decorate(big_trouser)
sneakers.show()
main()
運動鞋
垮褲
T恤
裝扮的張賀
點評
上述客戶端代碼可以用自然語言描述為:
- 實例化沒穿衣服的人類
- 為沒穿衣服的人類穿上T恤
- 為穿著T恤的人類穿上垮褲
- 為穿著T恤,垮褲的人類穿上運動鞋
所以,裝飾模型是為已有功能動態的添加更多功能的一種方式,它把每個要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的對象,因此,當需要執行特殊行為時,客戶端代碼可以在運行時根據需要有選擇的,按順序的使用裝飾功能包裝對象。
裝飾模式的優點在於,把類中的裝飾功能從類中搬移出去,這樣可以簡化原有的類,有效的把類的核心職責
和裝飾功能
區分開了。而且可以去除相關類中重復的裝飾邏輯,即一個裝飾功能可以給多個不同的類使用。
[Python設計模式] 第6章 衣服搭配系統——裝飾模式