javascript
《JavaScript设计模式与开发实践》原则篇(3)—— 开放-封闭原则
在面向?qū)ο蟮某绦蛟O(shè)計(jì)中,開放封閉原則(OCP)是最重要的一條原則。很多時(shí)候,一個程序具有良好的設(shè)計(jì),往往說明它是符合開放封閉原則的。 當(dāng)需要改變一個程序的功能或者給這個程序增加新功能的時(shí)候,可以使用增加代碼的方式,但是不允許改動程序的源代碼。
故事背景
假設(shè)我們是一個大型 Web 項(xiàng)目的維護(hù)人員,在接手這個項(xiàng)目時(shí),發(fā)現(xiàn)它已經(jīng)擁有10萬行以上的JavaScript代碼和數(shù)百個 JS 文件。 不久后接到了一個新的需求,即在 window.onload 函數(shù)中打印出頁面中的所有節(jié)點(diǎn)數(shù)量。這 當(dāng)然難不倒我們了。于是我們打開文本編輯器,搜索window.onload函數(shù)在文件中的位置,在函數(shù)內(nèi)部添加以下代碼
window.onload = function(){ // 原有代碼略console.log( document.getElementsByTagName( '*' ).length ); }; 復(fù)制代碼應(yīng)用OCP原則
Function.prototype.after = function( afterfn ){ var __self = this;return function(){var ret = __self.apply( this, arguments ); afterfn.apply( this, arguments );return ret;} }; window.onload = ( window.onload || function(){} ).after(function(){ console.log( document.getElementsByTagName( '*' ).length ); }); 復(fù)制代碼通過動態(tài)裝飾函數(shù)的方式,我們完全不用理會從前 window.onload 函數(shù)的內(nèi)部實(shí)現(xiàn),就算拿到的是一份混淆壓縮過的代碼也沒有關(guān)系。只要它從前是個穩(wěn)定運(yùn)行的函數(shù),那么以后也不會因?yàn)槲覀兊男略鲂枨蠖a(chǎn)生錯誤。新增的代碼和原有的代碼可以互不影響。
編寫符合OCP代碼的方法
過多的條件分支語句是造成程序違反開放封閉原則的一個常見原因。每當(dāng)需要增加一個新 的 if 語句時(shí),都要被迫改動原函數(shù)。實(shí)際上,每當(dāng)我們看到一大片的 if 或者 swtich-case 語句時(shí),第一時(shí)間就應(yīng)該考慮,能否利用對象的多態(tài)性來重構(gòu)它們。
利用多態(tài)的思想
利用對象的多態(tài)性來讓程序遵守開放封閉原則,是一個常用的技巧。
- 不符合OCP
利用多態(tài)的思想,我們把程序中不變的部分隔離出來(動物都會叫),然后把可變的部分封 裝起來(不同類型的動物發(fā)出不同的叫聲),這樣一來程序就具有了可擴(kuò)展性。當(dāng)我們想讓一只狗發(fā)出叫聲時(shí),只需增加一段代碼即可,而不用去改動原有的 makeSound函數(shù)
var makeSound = function( animal ){ animal.sound(); }; var Duck = function(){}; Duck.prototype.sound = function(){ console.log( '嘎嘎嘎' ); }; var Chicken = function(){}; Chicken.prototype.sound = function(){ console.log( '咯咯咯' ); }; makeSound( new Duck() ); // 嘎嘎嘎 makeSound( new Chicken() ); // 咯咯咯 /********* 增加動物狗,不用改動原有的 makeSound 函數(shù) ****************/ var Dog = function(){}; Dog.prototype.sound = function(){ console.log( '汪汪汪' ); }; makeSound( new Dog() ); // 汪汪汪 復(fù)制代碼放置掛鉤
放置掛鉤(hook)也是分離變化的一種方式。我們在程序有可能發(fā)生變化的地方放置一個掛鉤,掛鉤的返回結(jié)果決定了程序的下一步走向。這樣一來,原本的代碼執(zhí)行路徑上就出現(xiàn)了一個 分叉路口,程序未來的執(zhí)行方向被預(yù)埋下多種可能性。
使用回調(diào)函數(shù)
在 JavaScript 中,函數(shù)可以作為參數(shù)傳遞給另外一個函數(shù),這是高階函數(shù)的意義之一。在這 種情況下,我們通常會把這個函數(shù)稱為回調(diào)函數(shù)。在 JavaScript版本的設(shè)計(jì)模式中,策略模式和命令模式等都可以用回調(diào)函數(shù)輕松實(shí)現(xiàn)。 回調(diào)函數(shù)是一種特殊的掛鉤。我們可以把一部分易于變化的邏輯封裝在回調(diào)函數(shù)里,然后把 回調(diào)函數(shù)當(dāng)作參數(shù)傳入一個穩(wěn)定和封閉的函數(shù)中。當(dāng)回調(diào)函數(shù)被執(zhí)行的時(shí)候,程序就可以因?yàn)榛?調(diào)函數(shù)的內(nèi)部邏輯不同,而產(chǎn)生不同的結(jié)果。
總結(jié)
開放封閉原則是一個看起來比較虛幻的原則,但我們還是能找到一些讓程序盡量遵守開放封閉原則的規(guī)律,最明顯的就是找出程序中將要發(fā)生變化的地方,然后把變化封裝起來。 通過封裝變化的方式,可以把系統(tǒng)中穩(wěn)定不變的部分和容易變化的部分隔離開來。在系統(tǒng)的 演變過程中,我們只需要替換那些容易變化的部分,如果這些部分是已經(jīng)被封裝好的,那么替換起來也相對容易。而變化部分之外的就是穩(wěn)定的部分。在系統(tǒng)的演變過程中,穩(wěn)定的部分是不需要改變的。
系列文章:
《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》最全知識點(diǎn)匯總大全
總結(jié)
以上是生活随笔為你收集整理的《JavaScript设计模式与开发实践》原则篇(3)—— 开放-封闭原则的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 低碳生活和低碳生活的具体做法是什么
- 下一篇: Micronaut for Spring