設計模式六大原則(3)——依賴倒置原則

定義:高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。

問題由來:類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類A一般是高層模塊,負責復雜的業務邏輯;類B和類C是低層模塊,負責基本的原子操作;假如修改類A,會給程序帶來不必要的風險。

解決方案:將類A修改為依賴接口I,類B和類C各自實現接口I,類A通過接口I間接與類B或者類C發生聯系,則會大大降低修改類A的幾率。

???????? 依賴倒置原則基于這樣一個事實:相對于細節的多變性,抽象的東西要穩定的多。以抽象為基礎搭建起來的架構比以細節為基礎搭建起來的架構要穩定的多。在java中,抽象指的是接口或者抽象類,細節就是具體的實現類,使用接口或者抽象類的目的是制定好規范和契約,而不去涉及任何具體的操作,把展現細節的任務交給他們的實現類去完成。

???????? 依賴倒置原則的核心思想是面向接口編程,我們依舊用一個例子來說明面向接口編程比相對于面向實現編程好在什么地方。場景是這樣的,母親給孩子講故事,只要給她一本書,她就可以照著書給孩子講故事了。代碼如下:

  1.  1 class Book{  
     2     public String getContent(){  
     3         return "很久很久以前有一個阿拉伯的故事……";  
     4     }  
     5 }  
     6   
     7 class Mother{  
     8     public void narrate(Book book){  
     9         System.out.println("媽媽開始講故事");  
    10         System.out.println(book.getContent());  
    11     }  
    12 }  
    13   
    14 public class Client{  
    15     public static void main(String[] args){  
    16         Mother mother = new Mother();  
    17         mother.narrate(new Book());  
    18     }  
    19 }  

    ?

運行結果:

媽媽開始講故事
很久很久以前有一個阿拉伯的故事……

??????? 運行良好,假如有一天,需求變成這樣:不是給書而是給一份報紙,讓這位母親講一下報紙上的故事,報紙的代碼如下:

  1. 1 class Newspaper{  
    2     public String getContent(){  
    3         return "林書豪38+7領導尼克斯擊敗湖人……";  
    4     }  
    5 } 

    ?

    ?

??????? 這位母親卻辦不到,因為她居然不會讀報紙上的故事,這太荒唐了,只是將書換成報紙,居然必須要修改Mother才能讀。假如以后需求換成雜志呢?換成網頁呢?還要不斷地修改Mother,這顯然不是好的設計。原因就是Mother與Book之間的耦合性太高了,必須降低他們之間的耦合度才行。

我們引入一個抽象的接口IReader。讀物,只要是帶字的都屬于讀物:

  1. 1 interface IReader{  
    2     public String getContent();  
    3 } 

    ?

    ?

Mother類與接口IReader發生依賴關系,而Book和Newspaper都屬于讀物的范疇,他們各自都去實現IReader接口,這樣就符合依賴倒置原則了,代碼修改為:

  1.  1 class Newspaper implements IReader {  
     2     public String getContent(){  
     3         return "林書豪17+9助尼克斯擊敗老鷹……";  
     4     }  
     5 }  
     6 class Book implements IReader{  
     7     public String getContent(){  
     8         return "很久很久以前有一個阿拉伯的故事……";  
     9     }  
    10 }  
    11   
    12 class Mother{  
    13     public void narrate(IReader reader){  
    14         System.out.println("媽媽開始講故事");  
    15         System.out.println(reader.getContent());  
    16     }  
    17 }  
    18   
    19 public class Client{  
    20     public static void main(String[] args){  
    21         Mother mother = new Mother();  
    22         mother.narrate(new Book());  
    23         mother.narrate(new Newspaper());  
    24     }  
    25 }  

    ?

運行結果:

媽媽開始講故事
很久很久以前有一個阿拉伯的故事……
媽媽開始講故事
林書豪17+9助尼克斯擊敗老鷹……

????這樣修改后,無論以后怎樣擴展Client類,都不需要再修改Mother類了。這只是一個簡單的例子,實際情況中,代表高層模塊的Mother類將負責完成主要的業務邏輯,一旦需要對它進行修改,引入錯誤的風險極大。所以遵循依賴倒置原則可以降低類之間的耦合性,提高系統的穩定性,降低修改程序造成的風險。

??? 采用依賴倒置原則給多人并行開發帶來了極大的便利,比如上例中,原本Mother類與Book類直接耦合時,Mother類必須等Book類編碼完成后才可以進行編碼,因為Mother類依賴于Book類。修改后的程序則可以同時開工,互不影響,因為Mother與Book類一點關系也沒有。參與協作開發的人越多、項目越龐大,采用依賴導致原則的意義就越重大。現在很流行的TDD開發模式就是依賴倒置原則最成功的應用。

???????? 傳遞依賴關系有三種方式,以上的例子中使用的方法是接口傳遞,另外還有兩種傳遞方式:構造方法傳遞setter方法傳遞,相信用過Spring框架的,對依賴的傳遞方式一定不會陌生。
在實際編程中,我們一般需要做到如下3點:

  • 低層模塊盡量都要有抽象類或接口,或者兩者都有。
  • 變量的聲明類型盡量是抽象類或接口。
  • 使用繼承時遵循里氏替換原則。

??????? 依賴倒置原則的核心就是要我們面向接口編程,理解了面向接口編程,也就理解了依賴倒置。

?

轉自:http://blog.csdn.net/zhengzhb/article/details/7289269

轉載于:https://www.cnblogs.com/zl1991/p/6283221.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/255583.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/255583.shtml
英文地址,請注明出處:http://en.pswp.cn/news/255583.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【機器學習——決策樹】——兩種方法實現,含模型的保存和調用

目錄 1、ID3算法 2、使用sklearn API——模型保存和調用成功 1、ID3算法 以下實現了決策樹的創建、可視化繪制、決策樹的保存和調用 但是在利用決策樹進行預測的時候出現錯誤 分類代碼 #實用決策樹進行分類 def classify(inputTree, featLabels, testVec): firstStr = in…

重溫 const 指針

在進行聲明指針時,可以在類型前或后使用關鍵字const,也可在兩個位置都使用。 下面都是合法的聲明,但是含義大不同: const int * pOne; //指向整形常量 的指針,它指向的值不能修改 int * const pTwo; //指向整…

提交MTBF eservice以及log注意事項

[DESCRIPTION]提交MTBFeservice需要注意的描述,log事項[SOLUTION]提交MTBF eservice時,請注意1.描述清楚問題現象2. 描述清楚問題發生的時間點3.描述清楚問題發生時在run的case提交log時請注意1.MTBF的log通常會很大,若log太大,只…

Apache Cassandra和Apache Ignite:關系并置和分布式SQL

為什么80%的碼農都做不了架構師?>>> 在上一篇文章中,回顧和總結了Cassandra中使用的查詢驅動數據模型(或者說非常規數據模型)方法論的缺陷。事實證明,如果不對查詢有深入的了解,通過該方法論將…

Android高級開發專題晉升班

Android高級開發專題晉升班 適用人群:1-3年以上經驗的開發者丨學員平均薪酬20K/月轉載于:https://www.cnblogs.com/lythonliu/p/6285531.html

使用opencv簡單的播放AVI程序(40行)

學習OPENCV的第一個例子 #include <highgui.h> #include <cassert> #include <iostream> #include <Windows.h> using namespace std; void OnTrackbarSlide(int pos);int g_slider_position 0; CvCapture *g_capture NULL; int main(int argc , cha…

【糾錯】——mysql Authentication plugin ‘caching_sha2_password‘ is not supported問題處理

mysql Authentication plugin ‘caching_sha2_password’ is not supported問題處理 使用mysql8.0版本&#xff0c;登錄失敗&#xff0c;提示 Authentication plugin ‘caching_sha2_password’ is not supported。 原因是在MySQL 8.0以后&#xff0c;默認的密碼加密方式是cac…

關于EL表達式取值的問題

EL表達式取值時,如果沒有指定作用域,EL表達式會自動按照作用域的大小,從小到大依次去找;比如${s},會自動按照"pageContext,request,session,application"的順序去找屬性名為s的屬性.如果找到,則顯示.否則,什么都不顯示. 當Map中存整數時,如果想采用EL表達式取值,Map的…

統計信息自動收集任務失效原因排查

環境&#xff1a;Oracle 11.2.0.3 RAC問題&#xff1a;統計信息自動收集任務失效原因排查 1.查看自動任務的狀態2.進一步查看其它信息3.解決問題1.查看自動任務的狀態 查看自動任務的狀態&#xff0c;確認是enabled狀態&#xff1a; SQL> select client_name,status from db…

Markdown使用

#一級標題 ##二級標題 ###三級標題 斜體 粗體 斜體粗體 代碼段> 刪除內容效果是&#xff1a; 這是一級標題 這是二級標題 這是三級標題 這是斜體這是粗體這是斜體粗體 代碼段 FileInputStream is new FileInputStream("text"); byte[] iput new byte[1024]; is.…

灰度圖的width和widthstep的區別

灰度圖的width是表示圖像的每行像素數&#xff0c;widthstep指表示存儲一行像素需要的字節數。 在OpenCV里邊&#xff0c;widthStep必須是4的倍數&#xff0c;從而實現字節對齊&#xff0c;有利于提高運算速度。 如果8U單通道圖像寬度為3&#xff0c;那么widthStep是4&#xff…

【pyradiomics學習】——安裝pyradiomics以及簡單示例

目錄 數據集下載&#xff1a; 示例代碼 參考文獻&#xff1a; bug修復 運行結果&#xff1a; 數據集下載&#xff1a; https://www.jianguoyun.com/p/DcEwQq0Q45bOBxj09JYC (訪問密碼: gd8dmv) 示例代碼 #!/usr/bin/env python # -*- coding: utf-8 -*- # Time : 20…

最新Django2.0.1在線教育零基礎到上線教程(九)

演示地址&#xff1a; http://mxonline.mtianyan.cn 教程倉庫地址1: https://github.com/mtianyan/DjangoGetStarted 教程倉庫地址2: https://github.com/mtianyan/Mxonline2 教程倉庫地址3: https://github.com/mtianyan/Mxonline3 9-1 講師列表頁 teacherlist 和 teacher det…

過濾器 攔截器 區別

轉 http://www.cnblogs.com/wangyuyu/archive/2013/07/02/3167354.html1、攔截器是基于java的反射機制的&#xff0c;而過濾器是基于函數回調 2、過濾器依賴與servlet容器&#xff0c;而攔截器不依賴與servlet容器 3、攔截器只能對action請求起作用&#xff0c;而過濾器則可以對…

php --魔術常量 /魔術方法

魔術常量&#xff1a;1. __LINE__返回文件中的當前行號。2. __FILE__返回所在文件的完整路徑。包含文件名3. __FUNCTION__返回所在函數名稱。4. __CLASS__返回所在類的名稱。5. __METHOD__返回所在類方法的名稱。需要注意__METHOD__返回的是"class::function"的形式&…

【pyradiomics學習】——影像組學特征

目錄 1、形狀特征&#xff08;14個&#xff09; 2、一階特征&#xff08;18個&#xff09; 灰度共生矩陣特征&#xff08;24個&#xff09; 灰度區域大小矩陣特征&#xff08;16個&#xff09; 灰度行程矩陣特征&#xff08;16個&#xff09; 鄰域灰度差矩陣特…

NLP系列學習:前向算法和后向算法

在上一篇文章里,我們簡單的概述了隱馬爾科夫模型的簡單定義在<CRF-tutorial>這一篇文章里,我們可以看到HMM經過發展之后是CRF產生的條件,因此我們需要學好隱馬爾科夫模型.在這一部分,我比較推薦閱讀宗成慶老師的<自然語言處理>這本書,這一部分宗老師寫的很不錯,相關…

Java日期處理 開始時間-結束時間查詢

//開始時間 timeBegin " 00:00:00"; //結束時間 timeEnd " 23:59:59"; //時間轉換 SimpleDateFormat format new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //Java時間類型轉換成Long類型(可封裝成工具類) public static Long stringToLong(St…

angular路由操作中'#'字符的解決辦法

var appangular.module("myapp",["ngRoute"]);app.controller("ctr",function($scope){});//angular1.6.0以上版本需要配置app.config(["$locationProvider",function($locationProvider){ $locationProvider.hashPrefix(""…

【TypeError: float() argument must be a string or a number, not ‘map’】

初始 相關系數過濾法調用函數 from sklearn.feature_selection import SelectKBest from scipy.stats import pearsonr SelectKBest(lambda X,Y:np.array(map(lambda x:pearsonr(x,Y),X.T)).T,k2) .fit_transform(X_test,y_test) TypeError: float() argument must be a strin…