搜尋
首頁web前端js教程深入理解JavaScript系列(21):S.O.L.I.D五大原則之介面隔離原則ISP詳解_基礎知識

前言

本章我們要說明的是S.O.L.I.D五大原則JavaScript語言實作的第4篇,介面隔離原則ISP(The Interface Segregation Principle)。

英文原文:http://freshbrewedcode.com/derekgreer/2012/01/08/solid-javascript-the-interface-segregation-principle/
註:這篇文章作者寫得比較繞口,所以大叔理解得也比較鬱​​悶,湊合著看吧,別深陷進去了
介面隔離原則的描述是:

複製程式碼 程式碼如下:

Clients should not be forced to depend on methods they do not use.

不應該強迫客戶依賴它們不用的方法。

當用戶依賴的接口方法即便只被別的用戶使用而自己不用,那它也得實現這些接口,換而言之,一個用戶依賴了未使用但被其他用戶使用的接口,當其他用戶修改該介面時,依賴該介面的所有使用者都將受到影響。這顯然違反了開閉原則,也不是我們所期望的。

介面隔離原則ISP和單一職責有點類似,都是用於聚集功能職責的,實際上ISP可以被理解才具有單一職責的程序轉化到一個具有公共接口的對象。

JavaScript介面

JavaScript下我們改如何遵守這個原則呢?畢竟JavaScript沒有介面的特性,如果介面就是我們所想的透過某種語言提供的抽象型別來建立contract和解耦的話,可以說還行,不過JavaScript有另外一種形式的介面。在Design Patterns – Elements of Reusable Object-Oriented Software一書中我們找到了介面的定義:
http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612

一個物件宣告的任一操作都包含一個操作名稱,參數物件和操作的回傳值。我們稱之為操作符的簽名(signature)。
一個物件裡聲明的所有的操作被稱為這個物件的介面(interface)。一個物件的介面描繪了所有發生在這個物件上的請求資訊。
不管一種語言是否提供一個單獨的構造來表示接口,所有的物件都有一個由該物件所有屬性和方法組成的隱式接口。參考如下碼:

複製程式碼 程式碼如下:

var exampleBinder = {};
exampleBinder.modelObserver = (function() {
    /* 私人變數 */
    return {
        observe: function(model) {
            /* 代碼 */
            return newModel;
        },
        onChange: function(callback) {
            /* 代碼 */
        }
    }
})();

exampleBinder.viewAdaptor = (function() {
    /* 私人變數 */
    return {
        bind: function(model) {
            /* 代碼 */
        }
    }
})();

exampleBinder.bind = function(model) {
    /* 私人變數 */
    exampleBinder.modelObserver.onChange(/* 回呼callback */);
    var om = exampleBinder.modelObserver.observe(model);
    exampleBinder.viewAdaptor.bind(om);
    return om;
};

上面的exampleBinder類別庫實現的功能是雙向綁定。這個類別庫暴露的公共介面是bind方法,其中bind裡用到的關於change通知和view互動的功能分別是由單獨的物件modelObserver和viewAdaptor來實現的,這些物件從某種意義上來說就是公共介面bind方法的具體實作。

儘管JavaScript沒有提供介面類型來支援物件的contract,但該物件的隱式介面依然能當做一個contract提供給程式使用者。

ISP與JavaScript

我們下面討論的一些小節是JavaScript裡關於違反介面隔離原則的影響。如同上面所看到的,JavaScript程式裡實作介面隔離原則雖然可惜,但是不像靜態型別語言那麼強大,JavaScript的語言特性有時候會讓所謂的介面搞得有點不黏性。

墮落的實現

在靜態型別語言裡,導致違反ISP原則的一個原因是墮落的實現。在Java和C#裡所有的介面裡定義的方法都必須實現,如果你只需要其中幾個方法,那麼其他的方法也必須實現(可以透過空實作或是拋異常的方式)。在JavaScript裡,如果只需要一個物件裡的某一些介面的話,他也解決不了墮落實作這個問題,雖然不用強制實作上面的介面。但是這種實現依然違反了里氏替換原則。

複製程式碼 程式碼如下:

var rectangle = {
    area: function() {
        /* 代碼 */
    },
    draw: function() {
        /* 代碼 */
    }
};

var geometryApplication = {
    getLargestRectangle: function(rectangles) {
        /* 代碼 */
    }
};

var drawingApplication = {
    drawRectangles: function(rectangles) {
       /* 代碼 */
    }
};

當一個rectangle替代品為了滿足新物件geometryApplication的getLargestRectangle 的時候,它只需要rectangle的area()方法,但它卻違反了LSP(因為他根本用不到其中drawRectangles方法才能用到的draw方法)。

靜態耦合

靜態型別語言裡的另一個導致違反ISP的原因是靜態耦合,在靜態型別語言裡,介面在一個鬆散耦合設計程式裡扮演了重大角色。不管是在動態語言還是在靜態語言,有時候一個物件都可能需要在多個客戶端使用者進行通訊(例如共享狀態),對靜態類型語言,最好的解決方案是使用Role Interfaces,它允許使用者和該物件進行互動(而該物件可能需要在多個角色)作為它的實作來對使用者和無關的行為進行解耦。在JavaScript裡就沒有這種問題了,因為物件都被動態語言特有的優點進行解耦了。

語意耦合

導致違反ISP的一個通用原因,動態語言和靜態類型語言都有,那就是語義耦合,所謂語義耦合就是互相依賴,也就是一個對象的行為依賴於另外一個對象,那就意味著,如果一個使用者改變了其中一個行為,很有可能會影響另一個使用使用者。這也違反單一職責原則了。可以透過繼承和物件替代來解決這個問題。

可擴充性

另一個導致問題的原因是關於可擴展性,很多人在舉例的時候都會舉關於callback的例子用來展示可擴展性(比如ajax裡成功以後的回調設定)。如果想這樣的介面需要一個實作並且這個實作的物件裡有很多熟悉或方法的話,ISP就會變得很重要了,也就是說當一個介面interface變成了一個需求實作很多方法的時候,他的實作將會變得異常複雜,而且有可能導致這些介面承擔一個沒有黏性的職責,這就是我們經常提到的胖介面。

總結

JavaScript裡的動態語言特性,使得我們實現非黏性介面的影響力比靜態型別語言小,但介面隔離原則在JavaScript程式設計模式裡依然有它發揮作用的地方。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
1 個月前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)