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