摘要:什么是裝飾者模式今天我們來講另外一個非常實用的設計模式裝飾者模式。就增加功能來說,裝飾者模式相比生成子類更為靈活。下面,裝飾者模式就要正式登場了。下一步,我們可以愉快的去使用裝飾者模式啦
什么是裝飾者模式
今天我們來講另外一個非常實用的設計模式:裝飾者模式。這個名字聽上去有些莫名其妙,不著急,我們先來記住它的一個別名:包裝器模式。
我們記著這兩個名字來開始今天的文章。
首先還是上《設計模式》一書中的經典定義:
動態地給一個對象添加一些額外的職責。
就增加功能來說,裝飾者模式相比生成子類更為靈活。
我們來分析一下這個定義。
給對象添加一些新的職責,我們很容易想到創建子類來繼承父類,然后在子類上增加額外的職責。
那什么是動態地呢?應該就是說這些新添加的職責在類一開始創建的時候我們并不知道,而是在使用過程根據需要而添加的。
相比生成子類更為靈活,這句話讓裝飾者模式和子類繼承赤裸裸的刀兵相見了。沒有對比就沒有傷害,那我們就用例子來驗證這句話。
傳統面向對象的實現我們假設你是以為已經走上人生巔峰的汽車生產商,你的公司生產各種用途的汽車,某一天一個客戶下單了四種汽車,分別是家用轎車、SUV、旅行車和跑車。我們很輕松地像下面這樣進行交付了。
var Car = function(){} Car.prototype.start = function(){ console.log("轟轟轟,啟動正常!") } var Sedan = new car();// 小轎車 var Suv = new Car();// SUV var Wagon=new Car();// 旅行車 var Roadster=new Car();// 跑車 //是不是又學會了幾個英文單詞?
過了幾天客戶找來了,說最近人們愛上了西藏自駕游,人們都希望能夠選裝一些方便越野和載物的功能,比如加裝雪地胎、行李箱,升高底盤。
有經驗的你滿口答應下來,這個簡單,于是你交付了下面的代碼:
//SUV Suv.prototype.changeTire = function(){ console.log("我換了雪地胎"); } Suv.prototype.addHeight = function(){ console.log("我升高了底盤"); } Suv.prototype.addBox = function(){ console.log("我安裝了行李箱"); } //Wagon Wagon.prototype.changeTire = function(){ console.log("我換了雪地胎"); } Wagon.prototype.addHeight = function(){ console.log("我升高了底盤"); } Wagon.prototype.addBox = function(){ console.log("我安裝了行李箱"); } //Sedan Sedan.prototype.changeTire = function(){ console.log("我換了雪地胎"); } Sedan.prototype.addHeight = function(){ console.log("我升高了底盤"); } Sedan.prototype.addBox = function(){ console.log("我安裝了行李箱"); } // 使用 var suv = new Suv(); suv.changeTire(); suv.addHeight(); suv.addBox(); suv.start(); ...
你增加了多少種特性?3x3=9種。
你又問,我直接把這三個特性加在Car上不行嗎?就不用這么麻煩了。
當然不行,因為我們還有一種車:Roadster跑車。
你能想象法拉利換了雪地胎背上行李箱升高底盤是個什么死樣子嗎?這么干的人肯定瘋了。
如果我們把特性一股腦加在Car上,就避免不了這種情況的發生。
這個時候,就體現出子類繼承的不靈活之處。
下面,裝飾者模式就要正式登場了。
var Car=function (){} Car.prototype.start=function(){ console.log("轟轟轟,啟動正常!") } // 創建裝飾類(包裝類) var ChangeTireDec=function(car){ this.car=car; } var AddHeightDec=function(car){ this.car=car; } var AddBoxDec=function(car){ this.car=car; } // 裝飾類具有和Car同樣的特性,只不過額外執行了一些其他的操作 ChangeTireDec.prototype.start=function(){ console.log("我換了雪地胎"); this.car.start(); } AddHeightDec.prototype.start=function(car){ console.log("我升高了底盤"); this.car.start(); } AddBoxDec.prototype.start=function(car){ console.log("我安裝了行李箱"); this.car.start(); } // 使用 var suv=new Suv(); suv=new ChangeTireDec(suv); suv=new AddHeightDec(suv); suv=new AddBoxDec(suv); suv.start();
上面的代碼你增加了幾種特性?只有三種!而且不管你是給SUV還是Wagon還是Sedan加裝,都不需要再增加特性的代碼。
這,就是裝飾者模式的優勢所在。
現在我們再回過頭來看看GoF的定義:
動態地給一個對象添加一些額外的職責。
就增加功能來說,裝飾者模式相比生成子類更為靈活。
怎么樣,是不是如同1+1=2一樣簡單了?現在你應該也明白了為什么裝飾者模式又叫座包裝器模式了。因為它將類的原有特性包裝起來,添加其他的特性,就像一個箱子一樣。而且實現過程中,還滿足了封閉-開放原則。
JavaScript的實現上面的例子中,我們是模擬了傳統的面向對象語言來解釋什么是裝飾者模式。我們都知道,要動態改變JavaScript對象非常容易,可以向操作變量一個操作對象,我們再來改寫下上面的例子,讓它更javasripty
var car = { start: function(){ console.log("轟轟轟,正常啟動!"); } } var ChangeTireDec = function(){ console.log("我換了雪地胎"); } var AddHeightDec = function(){ console.log("我升高了底盤"); } var AddBoxDec = function(){ console.log("我安裝了行李箱"); } var start1 = car.start; car.start=function(){ ChangeTireDec(); start1(); } var start2=car.start; car.start = function(){ AddHeightDec(); start2(); } var start3=car.start(); car.start = function(){ AddBoxDec(); start3(); } // 執行 car.start();實際中的應用
從上面的例子我們可以看出來,我們不斷的將car.start的引用賦值給臨時變量,然后將原來的car.start指向新的對象--包含了原來對象的引用和新的特性的對象。這很好的保證了代碼的開放-封閉原則,這是今天第二次提到這個原則了,就是對修改封閉,對新增開放。
特別當你要重構一個非常復雜的多人項目時,如果你不想因為修改了同事的一行代碼而引起“蝴蝶效應”,那么將他的方法整個打包賦值然后用裝飾者模式增加新的功能,是一種非常安全而且高效的做法。
下一步,我們可以愉快的去使用裝飾者模式啦!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107792.html
摘要:做前端開發已經好幾年了,對設計模式一直沒有深入學習總結過。今天第一天,首先來講策略模式。什么是策略模式四兄弟的經典設計模式中,對策略模式的定義如下定義一系列的算法,把它們一個個封裝起來,并且使它們可互相替換。 做前端開發已經好幾年了,對設計模式一直沒有深入學習總結過。隨著架構相關的工作越來越多,越來越能感覺到設計模式成為了我前進道路上的一個阻礙。所以從今天開始深入學習和總結經典的設計模...
摘要:測試類設計模式裝飾者模式工廠模式只能讀啦會報錯只讀異??梢哉_運行第二部分定義抽象組件是具體組件和抽象裝飾類的共同父類,聲明了在具體組件中實現的方法。 前言 本篇文章分為四個部分:第一部分會舉一個例子引出裝飾者模式,讓讀者對裝飾者模式有個感官上的認識;第二部分會給出裝飾者模式的定義(當然我們主要不是來背定義,就當做積累專業名詞來記吧,我個人是很不喜歡下定義的);第三部分,我會拿jdk中...
摘要:作者按每天一個設計模式旨在初步領會設計模式的精髓,目前采用和兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式原文地址是每天一個設計模式之裝飾者模式歡迎關注個人技術博客。 作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript和python兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式...
摘要:作者按每天一個設計模式旨在初步領會設計模式的精髓,目前采用和兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式原文地址是每天一個設計模式之裝飾者模式歡迎關注個人技術博客。 作者按:《每天一個設計模式》旨在初步領會設計模式的精髓,目前采用javascript和python兩種語言實現。誠然,每種設計模式都有多種實現方式,但此小冊只記錄最直截了當的實現方式...
閱讀 2969·2021-11-25 09:43
閱讀 3586·2021-11-24 11:13
閱讀 3354·2021-10-14 09:42
閱讀 2556·2021-09-23 11:53
閱讀 3605·2021-09-22 15:57
閱讀 3221·2021-09-02 09:54
閱讀 3499·2019-08-30 13:47
閱讀 1638·2019-08-29 16:55