摘要:當接口比較多,裝飾器也比較多時,可以獨立抽取一個裝飾器父類,實現目標類的所有接口,再創建真正的裝飾器來繼承這個父類。四的實現方式提供了一種類似的注解的語法糖,來實現裝飾者模式。
歡迎關注我的公眾號睿Talk,獲取我最新的文章:
所謂裝飾者模式,就是動態的給類或對象增加職責的設計模式。它能在不改變類或對象自身的基礎上,在程序的運行期間動態的添加職責。這種設計模式非常符合敏捷開發的設計思想:先提煉出產品的MVP(Minimum Viable Product,最小可用產品),再通過快速迭代的方式添加功能。
二、傳統面向對象語言的實現方式var Car = function() {} Car.prototype.drive = function() { console.log("乞丐版"); } var AutopilotDecorator = function(car) { this.car = car; } AutopilotDecorator.prototype.drive = function() { this.car.drive(); console.log("啟動自動駕駛模式"); } var car = new Car(); car = new AutopilotDecorator(car); car.drive(); //乞丐版;啟動自動駕駛模式;
這種方式的實現要點是裝飾器類要維護目標對象的一個引用,同時要實現目標類的所有接口(這個例子里的drive方法,如果還有其它方法,比如brake,AutopilotDecorator也要實現)。調用方法時,先執行目標對象原有的方法,再執行自行添加的特性。
當接口比較多,裝飾器也比較多時,可以獨立抽取一個裝飾器父類,實現目標類的所有接口,再創建真正的裝飾器來繼承這個父類。
var Car = function() {} Car.prototype.drive = function() { console.log("乞丐版"); } /* 多了一個剎車方法 */ Car.prototype.brake = function() { console.log("剎車"); } /* 實現所有接口的裝飾器父類 */ var CarDecorator = function(car) { this.car = car; } CarDecorator.prototype = { drive: function() { this.car.drive(); }, brake: function() { this.car.brake(); } } /* 真正的裝飾器 */ var AutopilotDecorator = function(car) { CarDecorator.call(this, car); } AutopilotDecorator.prototype = new CarDecorator(); AutopilotDecorator.prototype.drive = function() { this.car.drive(); console.log("啟動自動駕駛模式"); } /* 真正的裝飾器 */ var HybridDecorator = function(car) { CarDecorator.call(this, car); } HybridDecorator.prototype = new CarDecorator(); HybridDecorator.prototype.brake = function() { this.car.brake(); console.log("啟動充電模式"); } var car = new Car(); car = new AutopilotDecorator(car); car = new HybridDecorator(car); car.drive(); //乞丐版;啟動自動駕駛模式; car.brake(); //剎車;啟動充電模式;三、JS基于對象的實現方式
var car = { drive: function() { console.log("乞丐版"); } } var driveBasic = car.drive; var autopilotDecorator = function() { console.log("啟動自動駕駛模式"); } var carToDecorate = Object.create(car); carToDecorate.drive = function() { driveBasic(); autopilotDecorator(); } carToDecorate.drive(); //乞丐版;啟動自動駕駛模式;
這種實現方式完全是基于JS自身的語言特點做考量。定義類的目的是實現代碼的封裝和復用,而JS這門語言是沒有類的概念的。它只有2種數據類型:基本類型和對象類型。實現邏輯的封裝和代碼的重用只需要通過對象來組織代碼,然后利用原生提供的克隆機制(Object.create)來達到目的。
從代碼的角度看,如果想擴展drive方法,只需要用一個變量來保存原函數的引用,然后再重寫drive方法就可以了。在重寫的方法里面,只要記得調用方法原有的行為就行。
另外,我們可以通過以下的工具函數,達到裝飾函數的目的:
Function.prototype.after = function(afterfn) { var _self = this; return function() { var ret = _self.apply(this, arguments); afterfn.apply(this, arguments); return ret; } } var car = { drive: function() { console.log("乞丐版"); } } var autopilotDecorator = function() { console.log("啟動自動駕駛模式"); } var carToDecorate = Object.create(car); carToDecorate.drive = car.drive.after(autopilotDecorator); carToDecorate.drive(); //乞丐版;啟動自動駕駛模式;
通過在Function的原型鏈上定義after函數,給所有的函數都賦予了被擴展的功能,當然也可以根據需要定義一個before的函數,在函數執行前去做一些操作。這種實現方式借鑒了AOP(Aspect Oriented Programming,面向切面編程)的思想。
四、ES7的實現方式ES7提供了一種類似的Java注解的語法糖decorator,來實現裝飾者模式。使用起來非常簡潔:
function autopilotDecorator(target, key, descriptor) { const method = descriptor.value; descriptor.value = () => { method.apply(target); console.log("啟動自動駕駛模式"); } return descriptor; } class Car { @autopilotDecorator drive() { console.log("乞丐版"); } } let car = new Car(); car.drive(); //乞丐版;啟動自動駕駛模式;
decorator的實現依賴于ES5的Object.defineProperty方法。defineProperty所做的事情是為一個對象增加新的屬性,或者更改某個已存在的屬性。調用方式是Object.defineProperty(obj, prop, descriptor)。
var o = {}; // 創建一個新對象 // 在對象中添加一個屬性 Object.defineProperty(o, "name", { value : "Dickens", writable : true, enumerable : true, configurable : true }); // 在對象中添加一個方法 Object.defineProperty(o, "sayHello", { value : function() { console.log("Hello, my name is: ", this.name) }, writable : true, enumerable : true, configurable : true }); o.sayHello() //Hello, my name is: Dickens
decorator的參數跟defineProperty是完全一樣的,含義也類似,通過修改descripter,就能達到擴展功能的目的。
五、總結本文介紹了裝飾者模式的基本概念,并通過不同的實現方式來介紹使用方法。對于不同的使用方法,也作了比較透徹的解釋,讓大家不但知其然,還知其所以然。
裝飾者模式是一種十分常用且功能強大的模式,利用ES7的語法糖,我們能用非常簡潔的方式來表達裝飾的意圖,推薦大家在實際項目中用起來。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93344.html
摘要:裝飾者模式裝飾者模式就是動態的給類或對象增加功能的設計模式。下的實現里的裝飾器目前處在建議征集的第二階段,不被瀏覽器所支持,如果想要提前使用這個新特性就需要,等工具進行轉譯。這里介紹下的用法。 1.1、裝飾者模式 裝飾者模式就是動態的給類或對象增加功能的設計模式。在程序運行時動態的給一個具備基礎功能的類或對象添加新的功能,并且不會改變會破壞基礎類和對象的功能。先提煉出產品的最小可用產品...
摘要:設計模式裝飾者模式何為裝飾者,意思就是,在不影響對象主功能的情況下,再添加一些額外的功能,使對象具備更多的功能。與繼承相比,裝飾者是一種更靈活輕便的做法。 javascript設計模式 --- 裝飾者模式 何為裝飾者,意思就是,在不影響對象主功能的情況下,再添加一些額外的功能,使對象具備更多的功能。與繼承相比,裝飾者是一種更靈活輕便的做法。下面我們看看javascript里裝飾者模式 ...
摘要:但是,這樣做的后果就是,我們會不斷的改變本體,就像把鳳姐送去做整形手術一樣。在中,我們叫做引用裝飾。所以,這里引入的裝飾模式裝飾親切,熟悉,完美。實例講解裝飾上面那個例子,只能算是裝飾模式的一個不起眼的角落。 裝飾者,英文名叫decorator. 所謂的裝飾,從字面可以很容易的理解出,就是給 土肥圓,化個妝,華麗的轉身為白富美,但本體還是土肥圓。 說人話.咳咳~ 在js里面一切都是對...
摘要:自行車的基類如下其它方法那么我們可以先創建一個裝飾者模式基類這個基類其實沒有做什么事情,它只是接受一個實例,實現其對應的方法,并且將調用其方法返回而已。 showImg(https://segmentfault.com/img/bVbs3pt?w=650&h=651); 什么是裝飾者模式 裝飾者模式是一種為函數或類增添特性的技術,它可以讓我們在不修改原來對象的基礎上,為其增添新的能力和...
摘要:裝飾者要實現這些相同的方法繼承自裝飾器對象創建具體的裝飾器,也是接收作對參數接下來我們要為每一個功能創建一個裝飾者對象,重寫父級方法,添加我們想要的功能。 裝飾模式 僅僅包裝現有的模塊,使之 更加華麗 ,并不會影響原有接口的功能 —— 好比你給手機添加一個外殼罷了,并不影響手機原有的通話、充電等功能; 使用 ES7 的 decorator ES7 中增加了一個 decorator 屬性...
閱讀 712·2021-11-22 13:52
閱讀 1517·2021-09-27 13:36
閱讀 2818·2021-09-24 09:47
閱讀 2172·2021-09-22 15:48
閱讀 3600·2021-09-22 15:39
閱讀 1460·2019-08-30 12:43
閱讀 2918·2019-08-29 18:39
閱讀 3181·2019-08-29 12:51