1. 程式人生 > >設計模式學習之設計模式原則(一):單一職責原則和里氏替換原則

設計模式學習之設計模式原則(一):單一職責原則和里氏替換原則

學習設計模式,以《設計模式之禪》為藍本進行總結與學習,今天先記錄設計模式六大原則的兩個原則:單一職責原則(SRP)和里氏替換原則(LSP)。

單一職責原則

Single Responsibility Principle(SRP):There should never be more than one reason for a class to change.

看如下一個設計:


思考問題:

1、協議接通的變化會引起這個介面或實現類的變化嗎?

2、那資料傳送(想想看,電話不僅僅可以通話,還可以上網)的變化會引起這個介面或實現類的變化嗎?

很顯然會引起變化,這就不符合單一職責原則了,需要做如下改進:


改進後,上述兩種情況的變化僅會引起一個介面的變化而不影響其他介面。

單一職責的好處:

1、類的複雜性降低,實現什麼職責都有清晰明確的定義;

2、可讀性提高,因為複雜性降低,所以可讀性提高;

3、可維護性提高,可讀性提高,當然更加容易維護;

4、變更引起的風險降低,變更是必不可少的,如果介面的單一職責做得好,一個介面修改只對相應的實現類有影響,對其他的介面無影響,這對系統的擴充套件性、維護性都有非常大的幫助。

單一職責原則提出了一個編寫程式的標準,用“職責”或“變化原因”來衡量介面或類設計得是否優良,但是“職責”和“變化原因”都是不可度量的,因專案而異,因環境而異。

下面給出一個方法關聯了太多的職責:


改進的類:


改進後,呼叫更加明確。

對於單一職責原則,我的建議是介面一定要做到單一職責,類的設計儘量做到只有一個原因引起變化。

里氏替換原則

Liskov Substitution Principle(LSP), definition:

1If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a sub type of T.

如果對每一個型別為S的物件o1,都有型別為T的物件o2,使得以T定義的所有程式P在所有的物件o1都代換成o2時,程式P的行為沒有發生變化,那麼型別S是型別T的子型別。

2Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

所有引用基類的地方必須能透明地使用其子類的物件。

第二個定義是最清晰明確的,通俗點講,只要父類能出現的地方子類就可以出現,而且替換為子類也不會產生任何錯誤或異常,使用者可能根本就不需要知道是父類還是子類。但是,反過來就不行了,有子類出現的地方,父類未必就能適應

LSP為繼承定義了良好的原則:

1、子類必須完全實現父類的方法。

CS遊戲中的應用類圖:


如果有一把玩具槍(ToyGun),該如何實現?注意:玩具槍不可以射擊。



2、子類可以有自己的個性。

3、覆蓋或實現父類的方法時輸入引數可以被放大。

里氏替換原則要求制定一個契約,就是父類或介面,這種設計方法也叫做DesignbyContract(契約設計)。契約制定了,也就同時制定了前置條件和後置條件,前置條件就是你要讓我執行,就必須滿足我的條件;後置條件就是我執行完了需要反饋

方法中的輸入引數稱為前置條件,過載時,要求方法的輸入引數型別或數量不相同,在里氏替換原則要求下,就是子類的輸入引數寬於或等於父類的輸入引數,也就是說你寫的這個方法是不會被呼叫的。

4、覆寫或實現父類的方法時輸出結果可以被縮小。

父類的一個方法的返回值是一個型別T,子類的相同方法(過載或覆寫)的返回值為S,那麼里氏替換原則就要求S必須小於等於T

採用里氏替換原則的目的就是增強程式的健壯性,版本升級時也可以保持非常好的相容性。即使增加子類,原有的子類還可以繼續執行。在實際專案中,每個子類對應不同的業務含義,使用父類作為引數,傳遞不同的子類完成不同的業務邏輯,非常完美!


相關推薦

設計模式學習設計模式原則單一職責原則里氏替換原則

學習設計模式,以《設計模式之禪》為藍本進行總結與學習,今天先記錄設計模式六大原則的兩個原則:單一職責原則(SRP)和里氏替換原則(LSP)。 單一職責原則 Single Responsibilit

設計模式六大原則1單一職責原則

定義:不要存在多於一個導致類變更的原因。通俗的說,即一個類只負責一項職責。 問題由來:類T負責兩個不同的職責:職責P1,職責P2。當由於職責P1需求發生改變而需要修改類T時,有可能會導致原本執行正常的職責P2功能發生故障。 解決方案:遵循單一職責原則。分別建立兩個類T1

設計模式原則1單一職責原則

定義:不要存在多於一個導致類變更的原因。通俗的說,即一個類只負責一項職責。 問題由來:類T負責兩個不同的職責:職責P1,職責P2。當由於職責P1需求發生改變而需要修改類T時,有可能會導致原本執行正常的職責P2功能發生故障。 解決方案:遵循單一職責原則。分別建立兩個類T1、T2,使T1完成職責P1功能,T2完成

設計模式 - 七大設計原則- 迪米特法則與里氏替換原則

概述 簡單介紹一下七大設計原則: 開閉原則:是所有面向物件設計的核心,對擴充套件開放,對修改關閉 依賴倒置原則:針對介面程式設計,依賴於抽象而不依賴於具體 單一職責原則:一個介面只負責一件事情,只能有一個原因導致類變化 介面隔離原則:使用多個專門的介面,而不是使用一個總介面 迪米特法則(最少知道原則):

設計模式學習筆記 C#代碼

內容 編程 繼承 color 模式 c# 派生類 ive spa 《深入淺出設計模式》學習筆記第一章 原始需求和設計 事情是這樣開始的,公司需要做一套程序,鴨子,設計如下: 一個鴨子父類,多個派生類,三個可override的方法。 第一次需求變更 我們要會飛的鴨子!!!!

Javascript高級程序設計--讀書筆記面向對象

friend 自定義 包括 類型 有一個 問題 相同 elb 模式 哈哈哈萬物皆對象,終於到了js的面向對象篇。 一、屬性類型 (1)數據屬性 數據屬性包含一個數據值的位置,在這個位置可以寫入和讀取數值,數據屬性有四個描述器行為的特性 [[Configurable]]:表

小白的java學習路 “ 選擇結構

測試 exti 邏輯運算符 main system 有一個 學習 並且 oid if選擇結構: if選擇結構是根據條件判斷之後再做處理的一種語法結構。 1.if選擇結構的語法: public class Demo{ public static void main(

Linux學習shell 程式設計基礎

一、linux中經常和正則表示式聯合使用的工具 grep sed awk(自己去研究吧). 二,以grep為例,有以下正則操作 特殊符號彙總 特殊符號 代表意義 [:alnum:] 代表英文

spring原始碼學習路---IOC初探

首先把spring原始碼匯入,怎麼匯入百度下。 首先我們來說一下IOC,IOC是spring最核心的理念,包括AOP也要屈居第二,那麼IOC到底是什麼呢,四個字,控制反轉。 網上有不少是這麼解釋IOC的,說IOC是將物件的建立和依賴關係交給容器,這句話我相信不少人都知道,在我個人的理解

JavaScript學習小白篇

好好學習 ,天天向上。Are you ready? 一、JS概述 1. 什麼是JS? Javascript是(基於物件)和(事件驅動)的(客戶端指令碼)語言。 2. 哪一年?哪家公司?誰?第一個名字? 1995 網景 布蘭登 livescript 3. W3C第一套標準:ECMA-262

詳解深度學習經典網路架構九大框架彙總

目錄 0、概覽 2、總結 本文是對本人前面講的的一些經典框架的彙總。 純手打,如果有不足之處,可以在評論區裡留言。 0、概覽 1、個人心得 (1)LeNet:元老級框架,結構簡單,卻開創了卷積神經網路的新紀元,具有重要的學

原型設計工具Axure RP核心培訓教程入門

什麼是Auxre RP? Axure RP是一種線框圖,原型設計,流程圖和文件工具。使用Axure RP來建立和設定圖表樣式,為圖表頁面和元素新增互動性和註釋,並將完成的設計釋出到HTML以便通過Web瀏覽器檢視。(點選下方圖片可觀看視訊~)      

分散式跟蹤系統Zipkin的背景設計

       2010年穀歌發表了其內部使用的分散式跟蹤系統Dapper的論文(http://static.googleusercontent.com/media/research.google.com/zh-CN//archive/papers/dapper-2010-1.

RabbitMQ學習Linux下安裝

CentOS 6.2 64bit 安裝erlang及RabbitMQ Server 1、作業系統環境(CentOS 6.2 64bit) [[email protected] ~]# cat /etc/issue CentOS release 6.2 (Final) Kernel \r on

linux下C 程式設計學習多程序程式設計

一、程序概念 程序是作業系統中資源分配的最小單位,而執行緒是排程的最小單位。 一個程序,主要包含三個元素: a)        一個可以執行的程式; b)        和該程序相關聯的全部資料(包括變數,記憶體空間,緩衝區等等); c)        程式的執行上下文(

HTML5學習語義化標籤

一、為什麼HTML5要引入新語義標籤 在HTML5出現之前,我們一般採用DIV+CSS佈局我們的頁面。但是這樣的佈局方式不僅使我們的文件結構不夠清晰,而且不利於搜尋引擎爬蟲對我們頁面的爬取。為了解決上

Java併發包原始碼學習執行緒池ThreadPoolExecutor原始碼分析

Java中使用執行緒池技術一般都是使用Executors這個工廠類,它提供了非常簡單方法來建立各種型別的執行緒池: public static ExecutorService newFixedThreadPool(int nThreads) public static ExecutorService

詳解深度學習經典網路架構DPNDual Path Network

目錄 0、簡介 1、優勢 3、總結 0、簡介 論文:Dual Path Networks 演算法詳解: 介紹的duall path networks(DPN)是顏水成老師新作,2017年4月在arxiv上放出,對於影象分類的效果有一定提升。我們知

機器學習決策樹演算法

0 引言   決策樹是一種基本的分類和迴歸方法。決策樹模型呈樹形結構,在分類問題中,表示基於特徵對例項進行分類的過程。可以認為是if-then規則的集合,也可以認定是定義在特徵空間與類空間上的條件概率分佈。其主要特點是模型具有可讀性,分類速度快。學習時,利用訓

mybatis原始碼學習執行過程分析2——config.xml配置檔案mapper.xml對映檔案解析過程

在上一篇中跟蹤了SqlSessionFactory及SqlSession的建立過程。這一篇,主要跟蹤Mapper介面和XML檔案對映及獲取。 1.xml檔案的解析 1.1Mybatis-config.xml的解析 在SqlSessionFactor