前言
本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實作的第5篇,依賴倒置原則LSP(The Dependency Inversion Principle )。
英文原文:http://freshbrewedcode.com/derekgreer/2012/01/22/solid-javascript-the-dependency-inversion-principle/
依賴倒置原則
依賴倒置原則的描述是:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
高層模組不應該依賴低層模組,二者都應該依賴抽象
B. Abstractions should not depend upon details. Details should depend upon abstractions.
抽像不應該依賴細節,細節應該依賴抽象
依賴倒置原則的最重要問題是確保應用程式或框架的主要元件從非重要的底層元件實現細節解耦出來,這將確保程式的最重要的部分不會因為低層次元件的變化修改而受影響。
這個原則的第一部分是關於高層模組和低層模組之間的耦合方式,在傳統的分成架構中,高層模組(封裝了程式的核心業務邏輯)總是依賴低層的一些模組(一些基礎點)。當應用依賴倒置原則的時候,關係就反過來了。和高層模組依賴低層模組不同,依賴倒置是讓低層模組依賴高層模組裡定義的介面。舉例來說,如果要給程式進行資料持久化,傳統的設計是核心模組依賴一個持久化模組的API,而根據依賴倒置原則重構以後,則是核心模組需要定義持久化的API接口,然後持久化的實作實例需要實作核心模組定義的這個API介面。
原則的第二部分描述的是抽象和細節之間的正確關係。理解這一部分,透過了解C 語言比較有幫助,因為他的適用性比較明顯。
不像一些靜態類型的語言,C 沒有提供一個語言級別的概念來定義接口,那類定義和類實現之間到底是怎麼樣的呢,在C 裡,類通過頭文件的形式來定義,其中定義了原始檔案需要實作的類別成員方法和變數。因為所有的變數和私有方法都定義在頭檔裡,所以可以用來抽象化以便和實作細節之前解耦出來。透過定只定義抽象方法來實作(C 裡是抽象基底類別)介面這個概念用來實作類別來實作。
DIP and JavaScript
因為JavaScript是動態語言,所以不需要去為了解耦而抽象化。所以抽像不應依賴細節這個改變在JavaScript裡沒有太大的影響,但高層模組不應該依賴低層模組卻有很大的影響。
在當靜態型別語言的脈絡裡討論依賴倒置原則的時候,耦合的概念包括語意(semantic)和物理(physical)兩種。這就是說,如果一個高層模組依賴於一個低層模組,也就是不僅耦合了語義接口,也耦合了在底層模組裡定義的物理接口。也就是說高層模組不只從第三方類別庫解耦出來,也需要從原生的低層模組解耦出來。
為了解釋這一點,想像一個.NET程式可能包含一個非常有用的高層模組,而這個模組依賴一個低層的持久化模組。當作者需要在持久化API裡增加一個類似的介面的時候,不管依賴倒置原則有沒有使用,高層模組在不重新實作這個低層模組的新介面之前是沒有辦法在其它的程式裡得到重用的。
在JavaScript裡,依賴倒置原則的適用性僅限於高層模組和低層模組之間的語意耦合,例如,DIP可以根據需要去增加介面而不是耦合低層模組定義的隱式介面。
為了來理解這個,我們看一下如下例子:
$.fn.trackMap = 函數(選項) {
var 預設值 = {
/* 預設值 */
};
選項 = $.extend({}, 預設值, 選項);
var mapOptions = {
中心:新的 google.maps.LatLng(options.latitude,options.longitude),
縮放:12,
地圖類型 ID:google.maps.MapTypeId.ROADMAP
},
地圖 = new google.maps.Map(this[0], mapOptions),
pos = new google.maps.LatLng(options.latitude,options.longitude);
var mark = new google.maps.Marker({
地點: pos,
標題:選項.標題,
圖示:選項.icon
});
marker.setMap(map);
options.feed.update(function(緯度, 經度) {
marker.setMap(null);
var newLatLng = new google.maps.LatLng(緯度, 經度);
標記.position = newLatLng;
marker.setMap(地圖);
map.setCenter(newLatLng);
});
回此;
};
var updater = (function() {
// 私有屬性
回 {
更新:函數(回呼){
updateMap = 回調;
}
};
})();
$("#map_canvas").trackMap({
緯度: 35.044640193770725,
經度:-89.98193264007568,
圖示:'http://bit.ly/zjnGDe',
title: '追蹤號碼:12345',
摘要:更新器
});
在上述程式碼裡,一個小型的JS類別庫將一個DIV轉換成Map以便顯示目前追蹤的位置資訊。 trackMap函數有2個依賴:第三方的Google Maps API和Location feed。該feed物件的職責是當圖示位置更新的時候調用一個callback回呼(在初始化的時候提供的)並確定緯度緯度和精度經度。 Google Maps API是用來渲染介面的。
feed物件的介面可能遵循安裝,也可能沒有照裝trackMap函數的要求去設計,事實上,他的角色很簡單,形式在簡單的不同實現,不需要和Google Maps這麼依賴。採集上耦合了Google Maps API,如果需要切換不同的地圖那麼就必須對trackMap函數進行重構以便可以改裝不同的provider。
為了實現Google地圖類別庫的介面連接對接過來,我們需要重寫設計trackMap函數,以便對一個隱式介面(抽像出地圖式提供者的介面)進行介面連接,我們還需要一個介面連接Google Maps API的一個實作對象,如下是重構後的trackMap函數:
$.fn.trackMap = function(options) {
var defaults = {
/* defaults */
};
options = $.extend({}, defaults, options);
options.provider.showMap(
this[0],
options.latitude,
options.longitude,
options.icon,
options.title);
options.feed.update(function(latitude, longitude) {
options.provider.updateMap(latitude, longitude);
});
return this;
};
$("#map_canvas").trackMap({
latitude: 35.044640193770725,
longitude: -89.98193264007568,
icon: 'http://bit.ly/zjnGDe',
title: 'Tracking Number: 12345',
feed: updater,
provider: trackMap.googleMapsProvider
});
在該版本裡,我們重新設計了trackMap函數以及需要的一個地圖提供者接口,然後將實現的細節挪到了一個單獨的googleMapsProvider元件,該元件可能獨立封裝成一個單獨的JavaScript模組。如下是我的googleMapsProvider實作:
trackMap.googleMapsProvider = (function() {
var marker, map;
return {
showMap: function(element, latitude, longitude, icon, title) {
var mapOptions = {
center: new google.maps.LatLng(latitude, longitude),
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
},
pos = new google.maps.LatLng(latitude, longitude);
map = new google.maps.Map(element, mapOptions);
marker = new google.maps.Marker({
position: pos,
title: title,
icon: icon
});
marker.setMap(map);
},
updateMap: function(latitude, longitude) {
marker.setMap(null);
var newLatLng = new google.maps.LatLng(latitude,longitude);
marker.position = newLatLng;
marker.setMap(map);
map.setCenter(newLatLng);
}
};
})();
做了上述這些改變以後,trackMap函數將變得非常有彈性了,不必依賴Google Maps API,相反可以任意替換其它的地圖提供商,那就是說可以按照程式的需求去適配任何地圖提供者。
何時依賴注入?
有點不太相關,其實依賴注入的概念常常和依賴倒置原則混在一起,為了澄清這個不同,我們有必要來解釋一下:
依賴注入是控制反轉的一個特殊形式,反轉的意思一個元件如何取得它的依賴。依賴注入的意思是:依賴提供給元件,而不是元件去獲取依賴,意思是建立一個依賴的實例,透過工廠去請求這個依賴,透過Service Locator或元件自身的初始化去請求這個依賴。依賴倒置原則和依賴注入都是關注依賴,而且都是用來反轉。不過,依賴倒置原則沒有關注元件如何獲取依賴,而是只關注高層模組如何從低層模組解耦出來。某種意義上說,依賴倒置原則是控制反轉的另一種形式,這裡反轉的是哪個模組定義介面(從低層定義,反轉到高層定義)。
總結
這是五大原則的最後一篇了,在這5篇文字裡我們看到了SOLID如何在JavaScript裡實現的,不同的原則在JavaScript里通過不同的角度來說明的。 (大叔註:其實大叔覺得雖然是有點不倫不類,但從另一個層面上說,大體的原則在各種語言上其實還是一樣的。)

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Atom編輯器mac版下載
最受歡迎的的開源編輯器