這種「設計模式」,竟然是程式猿穿衣服時想出來的

這種「設計模式」,竟然是程式猿穿衣服時想出來的

程式設計師在妹子們心中一直處在「時尚雷區」的禁地,女人們票選出來最失敗的男士著裝幾乎都可以在程式設計師的身上找到標配。

和女生約會前會精心打扮不同,男生往往約會前什麼樣,約會時還是什麼樣,也有打扮之後反而用力過猛,更失敗的。

穿衣風格固然有很多:休閒、商務、運動潮男……無論你是剛下班還是打完球見妹子,都能穿出自己的 style。

但無論哪種風格,改頭換面總是需要多加嘗試才能找到合適自己的風格,(不求穿出小鮮肉男神範,但至少不能邋遢油膩對不對?)那麼,作為一枚程式猿有沒有什麼簡便的方法解決屌絲改頭換面的難題?

下面我們用程式模擬一下生活。

前陣子,Tony 因為換工作而搬了一次家,四室一廳的房子。裡面住了四個年輕人,有男孩也有女孩,而 Tony 也就在這裡遇上了自己喜歡的人,Jenny。

但 Tony 是一個程式猿,天生不善言辭,也不會穿衣打扮,和 Jenny 每天都低頭不見抬頭見卻總是被嫌棄:滿臉猥瑣,一副屌絲樣……

受到暴擊的 Tony 痛定思痛:一定要改善一下自己的形象,擺脫屌絲樣。於是叫上自己的死黨去了西單……

Tony 在大商城中兜兜轉轉,被各個商家教化著該怎樣搭配衣服: 襯衫要塞進褲子裡面,風衣不要系紐扣,領子要立起來……

在反覆試穿了一個晚上的衣服之後,終於找到一套還算湊合的行裝:下面是一條卡其色休閒褲配一雙深色休閒皮鞋,加一條銀色針釦頭的黑色腰帶;上面是一件紫紅色針織毛衣,內套一件白色襯衫;頭上帶一副方形黑框眼鏡。整體行裝雖不潮流,卻透露出一種工作人士的成熟、穩健和大氣。

這種「設計模式」,竟然是程式猿穿衣服時想出來的

我們就用程式來模擬這樣一個情景:

Tony 是一個程式設計師,給自己搭配了一套著裝:一條卡其色休閒褲,一雙深色休閒皮鞋,一條銀色針釦頭的黑色腰帶,一件紫紅色針織毛衣,一件白色襯衫,一副方形黑框眼鏡。

但類似的著裝也可以穿在其他的人身上,比如一個老師也可以這樣穿:一雙深色休閒皮鞋,一件白色襯衫,一副方形黑框眼鏡。

我們就用程式來模擬這樣一個情景。

原始碼示例:

原始碼示例:

class Person: “人” def __init__(self, name): self。__name = name def getName(self): return self。__name def wear(self): print(“我的著裝是:”)class Engineer(Person): “工程師” def __init__(self, name, skill): super()。__init__(name) self。__skill = skill def getSkill(self): return self。__skill def wear(self): print(“我是” + self。getSkill() + “工程師” + self。getName()) super()。wear()class Teacher(Person): “教師” def __init__(self, name, title): super()。__init__(name) self。__title = title def getTitle(self): return self。__title def wear(self): print(“我是” + self。getName() + self。getTitle()) super()。wear()class ClothingDecorator(Person): “服裝裝飾器” def __init__(self, person): self。_decorated = person def wear(self): self。_decorated。wear()class CasualPantDecorator(ClothingDecorator): “休閒褲” def __init__(self, person): super()。__init__(person) def wear(self): super()。wear() print(“一條卡其色休閒褲”)class BeltDecorator(ClothingDecorator): “腰帶” def __init__(self, person): super()。__init__(person) def wear(self): super()。wear() print(“一條銀色針釦頭的黑色腰帶”)class LeatherShoesDecorator(ClothingDecorator): “皮鞋” def __init__(self, person): super()。__init__(person) def wear(self): super()。wear() print(“一雙深色休閒皮鞋”)class KnittedSweaterDecorator(ClothingDecorator): “針織毛衣” def __init__(self, person): super()。__init__(person) def wear(self): super()。wear() print(“一件紫紅色針織毛衣”)class WhiteShirtDecorator(ClothingDecorator): “白色襯衫” def __init__(self, person): super()。__init__(person) def wear(self): super()。wear() print(“一件白色襯衫”)class GlassesDecorator(ClothingDecorator): “眼鏡” def __init__(self, person): super()。__init__(person) def wear(self): super()。wear() print(“一副方形黑框眼鏡”)

測試程式碼:

def testDecorator(): tony = Engineer(“Tony”, “客戶端”) pant = CasualPantDecorator(tony) belt = BeltDecorator(pant) shoes = LeatherShoesDecorator(belt) shirt = WhiteShirtDecorator(shoes) sweater = KnittedSweaterDecorator(shirt) glasses = GlassesDecorator(sweater) glasses。wear() print() decorateTeacher = GlassesDecorator(WhiteShirtDecorator(LeatherShoesDecorator(Teacher(“wells”, “教授”)))) decorateTeacher。wear()

上面的測試程式碼中

decorateTeacher = GlassesDecorator(WhiteShirtDecorator(LeatherShoesDecorator(Teacher(“wells”, “教授”))))

輸出結果:

我是客戶端工程師Tony我的著裝是:一條卡其色休閒褲一條銀色針釦頭的黑色腰帶一雙深色休閒皮鞋一件白色襯衫一件紫紅色針織毛衣一副方形黑框眼鏡我是wells教授我的著裝是:一雙深色休閒皮鞋一件白色襯衫一副方形黑框眼鏡

從劇情中思考裝飾模式:

上面的示例中,Tony 為了改善形象,整體換了著裝,改變了自己的氣質,使自己看起來不再是那麼猥瑣的屌絲樣。俗話說一個人帥不帥,三分看長相七分看打扮。

同一個人,不一樣的著裝,會給人完全不一樣的感覺。我們在不同場合搭配不同衣服以達到不同效果。

如果是參加一個正式會議或演講,可以穿一套標配西服;如果你是去大草原,想騎著駿馬馳騁天地,便該穿上一套馬服馬褲馬靴;如果你是漫迷,去參加動漫節當然要 cosplay 成自己嚮往的主角……

這樣一個時時刻刻發現在我們生活中的著裝問題,就是程式中裝飾模式的典型樣例。

裝飾模式

裝飾模式

(Decorator Pattern):動態地給一個物件增加一些額外的職責(Responsibility),就增加物件功能來說,裝飾模式比生成子類實現更為靈活。

就故事中這個示例來說,由結構龐大的子類繼承關係轉換成了結構緊湊的裝飾關係:

這種「設計模式」,竟然是程式猿穿衣服時想出來的

這種「設計模式」,竟然是程式猿穿衣服時想出來的

裝飾模式的特點

1. 可靈活地給一個物件增加職責或拓展功能

如上面的示例中,你可任意地穿上自己想穿的衣服。

q498552290交流

不管穿上什麼衣服,你還是那個你,但穿上不同的衣服你就會有不同的外表。

2. 可增加任意多個裝飾

你可以只穿一件衣服,也可以只穿一條褲子,也可以衣服和褲子各種搭配的穿,全隨你意!

3. 裝飾的順序不同,可能產生不同的效果。

在上面的示例中,Tony 是針織毛衣穿在外面,白色襯衫穿在裡面。當然,如果你願意(或因為怕冷),也可以針織毛衣穿在裡面,白色襯衫穿在外面。

但兩種著裝穿出來的效果,給人的感覺肯定是完全不一樣的,自己腦補一下,哈哈。

使用裝飾模式的方式,想要改變裝飾的順序,也是非常簡單的。只要把測試程式碼稍微改動一下即可,如下:

def testDecorator2(): tony = Engineer(“Tony”, “客戶端”) pant = CasualPantDecorator(tony) belt = BeltDecorator(pant) shoes = LeatherShoesDecorator(belt) sweater = KnittedSweaterDecorator(shoes) shirt = WhiteShirtDecorator(sweater) glasses = GlassesDecorator(shirt) glasses。wear()

結果如下:

我是客戶端工程師Tony我的著裝是:一條卡其色休閒褲一條銀色針釦頭的黑色腰帶一雙深色休閒皮鞋一件紫紅色針織毛衣一件白色襯衫一副方形黑框眼鏡

裝飾模式的模型抽象

類圖

透過上面的示例程式碼,我們知道了裝飾模式的一個典型實現。我們再將其抽象成一個一般化的類圖結構,如下:

這種「設計模式」,竟然是程式猿穿衣服時想出來的

上圖中的 Component 是一個抽象類,代表具有某中功能(function)的元件,ComponentImplA 和 ComponentImplB 分別是其具體的實現子類。

Decorator 是 Component 裝飾器,裡面有一個 Component 的物件 decorated,這就是被裝飾的物件,裝飾器可為被裝飾物件新增額外的功能或行為(addBehavior)。

DecoratorImplA 和 DecoratorImplB 分別是兩個具體的裝飾器(實現子類)。

這樣一種模式很好地將裝飾器與被裝飾的物件進行解耦。

模型說明

裝飾模式的優點:

1。 使用裝飾模式來實現擴充套件比繼承更加靈活,它可以在不需要創造更多子 類的情況下,將物件的功能加以擴充套件。

2。 可以動態地給一個物件附加更多的功能。

3。 可以用不同的裝飾器進行多重灌飾,裝飾的順序不同,可能產生不同的效果。

4。 裝飾類和被裝飾類可以獨立發展,不會相互耦合;裝飾模式相當於是繼承的一個替代模式。

裝飾模式的缺點:

與繼承相比,用裝飾的方式拓展功能更加容易出錯,排錯也更困難。對於多次裝飾的物件,除錯時尋找錯誤可能需要逐級排查,較為煩瑣。

應用場景

1。 有大量獨立的擴充套件,為支援每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。

2。 需要動態地增加或撤銷功能時。

3。 不能採用生成子類的方法進行擴充時,如類定義不能用於生成子類。

裝飾模式的應用場景非常廣泛。如在實際專案開發中經常看到的過濾器,便可用裝飾模式的方式去實現。

如果你是 Java 程式設計師,對 IO 中的 FilterInputStream 和 FilterOutputStream 一定不陌生,它的實現其實就是一個裝飾模式。

FilterInputStream(FilterOutputStream)就是一個裝飾器,而 InputStream(OutputStream)就是被裝飾的物件。

我們看一下建立物件過程:

DataInputStream dataInputStream = new DataInputStream(new FileInputStream(“C:/text。txt”));DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(“C:/text。txt”));

這個寫法與上面 Demo 中的

decorateTeacher = GlassesDecorator(WhiteShirtDecorator(LeatherShoesDecorator(Teacher(“wells”, “教授”))))

是不是很相似?都是一個物件套一個物件的方式進行建立。

還有一個場景,如果你對圖形影象處理有一定了解,就會知道對影象的處理其實就是對一個二維座標畫素資料的處理,如影象的灰度化、梯度化(銳化)、邊緣化、二值化。

這些操作順序不同就會造成不同的效果,也是適合用裝飾模式來進行封裝。

TAG: __SelfDeF裝飾Wear