摘要:如果非要重寫父類的方法,比較通用的做法是原來的父類和子類都繼承一個更通俗的基類,原有的繼承關(guān)系去掉,采用依賴聚合,組合等關(guān)系代替。里氏替換原則通俗的來講就是子類可以擴(kuò)展父類的功能,但不能改變父類原有的功能。一有限狀態(tài)機(jī)狀態(tài)總數(shù)是有限的。
設(shè)計模式 抽象類 抽象類的表現(xiàn)
不能被實例,只能被繼承
最少有一個抽象方法(多態(tài)的具體體現(xiàn))
// 汽車抽象類,當(dāng)使用其實例對象的方法時會拋出錯誤 var Car = function() {}; Car.prototype = { getPrice: function() { return new Error("抽象方法getPrice不能調(diào)用。"); }, getSpeed: function() { return new Error("抽象方法getSpeed不能調(diào)用。"); } };
上面Car類其實什么都沒有做,但用原型的方法還會直接報錯,這一特點非常有必要,因為總會有一些子類去繼承父類,這些父類經(jīng)常會去定義一些必要的方法,卻沒有具體的實現(xiàn).
一旦子類創(chuàng)建了一個對象,但是子類沒有重寫父類的方法而被調(diào)用,就會直接報錯,這個對大型項目中對子類的約束是非常有必要的,代碼頁更加清晰
單一職責(zé)原則...里氏替換原則
子類可以實現(xiàn)父類的抽象方法,但是不能覆蓋父類的非抽象方法
繼承作為面向?qū)ο笕筇匦灾?,在給程序設(shè)計帶來巨大便利的同時,也帶來了弊端。比如使用繼承會給程序帶來侵入性,程序的可移植性降低,增加了對象間的耦合性,如果一個類被其他的類所繼承,則當(dāng)這個類需要修改時,必須考慮到所有的子類,并且父類修改后,所有涉及到子類的功能都有可能會產(chǎn)生故障。
function Foo(){ this.aa="sdf"; } Foo.prototype.func1 = function(a,b){ return a-b; }; function Sub(){ } Sub.prototype = new Foo(); var demo = new Sub(); console.log("100-50="+demo.func1(100,50)); //運行結(jié)果: //100-50=50 //后來,我們需要增加一個新的功能:完成兩數(shù)相加,然后再與100求和,由類B來負(fù)責(zé)。即類B需要完成兩個功能: function Sub1 (){ } Sub1.prototype = new Foo(); Sub1.prototype.func1 = function(a,b){ return a+b; }; Sub1.prototype.func2 = function(a,b){ return this.func1(a,b)+100; }; var demo1 = new Sub1(); console.log("100-50="+demo1.func2(100,50)) //運行結(jié)果: //100-50=250
我們發(fā)現(xiàn)原本運行正常的相減功能發(fā)生了錯誤。原因就是類Sub1在給方法起名時無意中重寫了父類的方法,造成所有運行相減功能的代碼全部調(diào)用了類Sub1重寫后的方法,造成原本運行正常的功能出現(xiàn)了錯誤。在本例中,引用基類Foo完成的功能,換成子類Sub1之后,發(fā)生了異常。在實際編程中,我們常常會通過重寫父類的方法來完成新的功能,這樣寫起來雖然簡單,但是整個繼承體系的可復(fù)用性會比較差,特別是運用多態(tài)比較頻繁時,程序運行出錯的幾率非常大。如果非要重寫父類的方法,比較通用的做法是:原來的父類和子類都繼承一個更通俗的基類,原有的繼承關(guān)系去掉,采用依賴、聚合,組合等關(guān)系代替。開閉原則里氏替換原則通俗的來講就是:子類可以擴(kuò)展父類的功能,但不能改變父類原有的功能。它包含以下4層含義:
子類可以實現(xiàn)父類的抽象方法,但不能覆蓋父類的非抽象方法。
子類中可以增加自己特有的方法。
當(dāng)子類的方法重載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入?yún)?shù)更寬松。
當(dāng)子類的方法實現(xiàn)父類的抽象方法時,方法的后置條件(即方法的返回值)要比父類更嚴(yán)格。
看上去很不可思議,因為我們會發(fā)現(xiàn)在自己編程中常常會違反里氏替換原則,程序照樣跑的好好的。所以大家都會產(chǎn)生這樣的疑問,假如我非要不遵循里氏替換原則會有什么后果?
后果就是:你寫的代碼出問題的幾率將會大大增加。參考文檔:http://blog.csdn.net/zhengzhb...
function Foo(){ } Foo.prototype.getPerson = function(name){ if(name==="tom"){ return { name:"tom", age:"20" } }else if(name==="jack"){ return { name:"tom", age:"20", sex:"boy" } } } console.log(new Foo().getPerson("tom")); //這個時候 如果我要獲取名為lily這個人的屬性,就需要更改getPerson,這樣所有調(diào)用該接口的對象都會受到影響,這個時候我們?nèi)绾蝸碇貥?gòu) function Foo(){ } Foo.prototype.personInfo = function(){};//寫一個抽象方法 Foo.prototype.getPerson = function(){ return this.personInfo(); }; var a = new Foo(); a.personInfo=function(){ return { name:"lily", age:20, sex:"girl" } }; console.log(a.getPerson());狀態(tài)模式
狀態(tài)模式(State)允許一個對象在其內(nèi)部狀態(tài)改變的時候改變它的行為,對象看起來似乎修改了它的類。狀態(tài)模式的使用場景也特別明確,有如下兩點:
一個對象的行為取決于它的狀態(tài),并且它必須在運行時刻根據(jù)狀態(tài)改變它的行為。(有些對象通常會有好幾個狀態(tài),在每個狀態(tài)都只可以做當(dāng)前狀態(tài)才可以做的事情,而不能做其它狀態(tài)能做的事兒)
一個操作中含有大量的分支語句,而且這些分支語句依賴于該對象的狀態(tài)。狀態(tài)通常為一個或多個枚舉常量的表示。
一、有限狀態(tài)機(jī)
狀態(tài)總數(shù)(state)是有限的。
任一時刻,只處在一種狀態(tài)之中。
某種條件下,會從一種狀態(tài)轉(zhuǎn)變(transition)到另一種狀態(tài)。
// 狀態(tài)機(jī) var FSM = { off: { buttonWasPressed: function() { console.log("關(guān)燈"); this.button.innerHTML = "下一次按我是開燈"; // 這是Light上的屬性?。?! this.currState = FSM.on; // 這是Light上的屬性?。。? } }, on: { buttonWasPressed: function() { console.log("開燈"); this.button.innerHTML = "下一次按我是關(guān)燈"; this.currState = FSM.off; } }, }; var Light = function() { this.currState = FSM.off; // 設(shè)置當(dāng)前狀態(tài) this.button = null; }; Light.prototype.init = function() { var button = document.createElement("button"); self = this; button.innerHTML = "已關(guān)燈"; this.button = document.body.appendChild(button); this.button.onclick = function() { // 請求委托給FSM狀態(tài)機(jī) self.currState.buttonWasPressed.call(self); } } var light = new Light(); light.init();
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/95708.html
摘要:設(shè)計模式與開發(fā)實踐讀書筆記最近利用碎片時間在上面閱讀設(shè)計模式與開發(fā)實踐讀書這本書,剛開始閱讀前兩章內(nèi)容,和大家分享下我覺得可以在項目中用的上的一些筆記。事件綁定暫時這么多,以后會不定期更新一些關(guān)于我讀這本書的筆記內(nèi)容 JavaScript 設(shè)計模式與開發(fā)實踐讀書筆記 最近利用碎片時間在 Kindle 上面閱讀《JavaScript 設(shè)計模式與開發(fā)實踐讀書》這本書,剛開始閱讀前兩章內(nèi)容,...
摘要:保護(hù)代理和虛擬代理保護(hù)代理當(dāng)有許多需求要向某對象發(fā)出一些請求時,可以設(shè)置保護(hù)代理,通過一些條件判斷對請求進(jìn)行過濾。虛擬代理在程序中可以能有一些代價昂貴的操作。而虛擬代理是最常用的一種代理模式。 代理模式 代理模式是為一個對象提供一個代用品或占位符,以便控制對它的訪問。 保護(hù)代理和虛擬代理 保護(hù)代理:當(dāng)有許多需求要向某對象發(fā)出一些請求時,可以設(shè)置保護(hù)代理,通過一些條件判斷對請求進(jìn)行過濾。...
摘要:模式閱讀筆記第一部分函數(shù)模式總的來說模式是一本力薦的進(jìn)階書書里面涉及了很多在學(xué)習(xí)過程中會碰到的坑然后提供了很不錯的解決方法雖然很多人吐槽這本書的翻譯但是糟糕的翻譯還是無法掩蓋這是一本好書的事實因此這里我會結(jié)合書上的知識和我的理解來寫一些 Javascript模式 閱讀筆記-第一部分-函數(shù)模式 總的來說,javascript模式是一本力薦的js進(jìn)階書,書里面涉及了很多在學(xué)習(xí)javascr...
摘要:探討判斷橫豎屏的最佳實現(xiàn)前端掘金在移動端,判斷橫豎屏的場景并不少見,比如根據(jù)橫豎屏以不同的樣式來適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗。 探討判斷橫豎屏的最佳實現(xiàn) - 前端 - 掘金在移動端,判斷橫豎屏的場景并不少見,比如根據(jù)橫豎屏以不同的樣式來適配,抑或是提醒用戶切換為豎屏以保持良好的用戶體驗。 判斷橫豎屏的實現(xiàn)方法多種多樣,本文就此來探討下目前有哪些實現(xiàn)方法以及其中的優(yōu)...
摘要:因此,所有在方法中定義的變量都是放在棧內(nèi)存中的當(dāng)我們在程序中創(chuàng)建一個對象時,這個對象將被保存到運行時數(shù)據(jù)區(qū)中,以便反復(fù)利用因為對象的創(chuàng)建成本通常較大,這個運行時數(shù)據(jù)區(qū)就是堆內(nèi)存。 上一篇:《javascript高級程序設(shè)計》筆記:繼承近幾篇博客都會圍繞著圖中的知識點展開 showImg(https://segmentfault.com/img/bVY0C4?w=1330&h=618);...
摘要:策略模式可以避免代碼中的多重判斷條件。策略模式在程序中或多或少的增加了策略類。此文僅記錄本人閱讀設(shè)計模式與開發(fā)實踐這個本時的感受,感謝作者曾探寫出這么好的一本書。設(shè)計模式中很重要的一點就是將不變和變分離出來。參考設(shè)計模式與開發(fā)實踐曾探 策略模式的定義是:定義一系列的算法,把它們一個個封裝起來,并且是它們可以相互替換。 策略模式可以避免代碼中的多重判斷條件。 策略模式很好的體現(xiàn)了開放-...
閱讀 2662·2021-11-18 10:02
閱讀 2198·2021-10-13 09:40
閱讀 3111·2021-09-07 10:07
閱讀 2226·2021-09-04 16:48
閱讀 1101·2019-08-30 13:18
閱讀 2539·2019-08-29 14:03
閱讀 3018·2019-08-29 12:54
閱讀 3239·2019-08-26 11:41