1. 程式人生 > >設計模式原則——單一職責原則

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

單一職責原則(Single Responsibility Principle)

定義:一個物件應該只包含單一的職責,並且該職責被完整地封裝在一個類中。即:不要存在多於一個導致類變更的原因。通俗的說,就是一個類只負責一項職責。

問題由來:類T負責兩個不同的職責:職責P1,職責P2。當由於職責P1需求發生改變而需要修改類T時,有可能會導致原本執行正常的職責P2功能發生故障。

解決方案:遵循單一職責原則。分別建立兩個類T1、T2,使T1完成職責P1功能,T2完成職責P2功能。這樣,當修改類T1時,不會使職責P2發生故障風險;同理,當修改T2時,也不會使職責P1發生故障風險。

  雖然單一職責原則看起來如此簡單,但由於職責擴散,即便是經驗豐富的程式設計師寫出的程式,也會有違背這一原則的程式碼存在。所謂職責擴散,就是因為某種原因,職責P被分化成粒度更細的職責P1和P2。

  比如:開始時,類T只負責一個職責P,這符合單一職責原則。後來由於某種原因,需要將職責P細分為粒度更細的職責P1、P2,這時如果要使程式遵循單一職責原則,需要將類T也分解為兩個類T1和T2,來分別負責P1、P2兩個職責。但是在程式已經寫好的情況下,這樣做將會耗費大量時間和精力,所以,簡單地修改類T,用它來負責兩個職責是一個比較不錯的選擇,雖然這違背了單一職責原則。

  舉例說明,用一個類描述動物吃東西這個場景:

class Animal{
    public void eat(String animal){
       System.out.println(animal+"吃草");
    }
}

public class Client{
    public static void main(String[] args){
       Animal animal = new Animal();
       animal.eat("牛");
       animal.eat("羊");
       animal.eat("馬");
    }
}

執行結果:

牛吃草
羊吃草
馬吃草

  程式上線後,發現問題了,並不是所有的動物都是吃草的,比如狼就是吃肉的。修改時如果遵循單一職責原則,需要將Animal類細分為食草動物Herbivore和肉食性動物Carnivora,程式碼如下:

class Herbivore{
    public void eat(String animal){
       System.out.println(animal+"吃草");
    }
}

class Carnivora{
    public void eat(String animal){
       System.out.println(animal+"吃肉");
    }
}

public class Client{
    public static void main(String[] args){
       Herbivore herbivore = new Herbivore();
       herbivore.eat("牛");
       herbivore.eat("羊");
       herbivore.eat("馬");

       Carnivora carnivora = new Carnivora();
       carnivora.eat("狼");
    }
} 

執行結果:

牛吃草
羊吃草
馬吃草
狼吃肉

  我們發現這樣修改花銷是很大的,除了將原來的類分解之外,還需要修改客戶端。而直接修改類Animal來達成目的雖然違背了單一職責原則,但花銷卻要小的多,程式碼如下:

class Animal{
	public void eat(String animal){
		if("狼".equals(animal)){
			System.out.println(animal+"吃肉");
		}else{
			System.out.println(animal+"吃草");
		}
    }
}

public class Client{
	public static void main(String[] args){
		Animal animal = new Animal();
		animal.eat("牛");
		animal.eat("羊");
		animal.eat("馬");
		animal.eat("狼");
	}
}

  可以看到,這種修改方式要簡單得多,但是卻存在著隱患:有一天需要將狼分為北極狼和非北極狼,則又需要修改Animal類的eat方法,而對原有程式碼的修改會呼叫“牛”、“羊”、“馬”等相關功能帶來風險,也許某一天你會發現程式執行結果變成了“非北極狼吃草”了。這種修改方式直接在程式碼級別上違背了單一職責原則,雖然修改起來最簡單,但是隱患也是最大的。還有一種修改方式:

class Animal{
	public void eat(String animal){
		System.out.println(animal+"吃草");		
    }

	public void eat2(String animal){
		System.out.println(animal+"吃肉");		
    }
}

public class Client{
	public static void main(String[] args){
		Animal animal = new Animal();
		animal.eat("牛");
		animal.eat("羊");
		animal.eat("馬");
		animal.eat2("狼");
	}
}

  可以看到,這種修改方式沒有改動原來的方法,而是在類中新加了一個方法,這樣雖然也違背了單一職責原則,但在方法級別上卻是符合單一職責原則的,因為它並沒有動原來方法的程式碼。

  這三種方式各有優缺點,那麼在實際程式設計中,採用哪一種呢?其實這真的比較難說,需要根據實際情況來確定。我的原則是:只有邏輯足夠簡單,才可以在程式碼級別上違反單一職責原則;只有類中方法數量足夠少,才可以在方法級別上違反單一職責原則。在實際應用中的類都要複雜得多,一旦發生職責擴散而需要修改類時,除非這個類本身非常簡單,否則還是遵循單一職責原則的好。

遵循單一職責原則的優點

1、降低類的複雜性,類的職責清晰明確;

2、提高類的可讀性和可維護性;

3、變更引起的風險降低,變更是必然的,如果單一職責原則遵守的好,當修改一個功能時,可以顯著降低對其他功能的影響。

原文:http://www.cnblogs.com/lhws/archive/2012/03/10/2389189.html

相關推薦

《大話設計模式》——單一職責原則

有一個 導致 完成 如果能 原因 如果 分離 破壞 一個 單一職責原則(SRP):就一個類而言,應該僅有一個能引起它變化的原因。 如果一個類承擔的職責過多,就等於把這些職責耦合在一起,一個職責的變化可能會削弱或抑制這個類完成其他職責的能力。這種耦合會導致脆弱的設計,當變化發

嘻哈說:設計模式單一職責原則

1、定義 首先呢,我們來看一下單一職責原則的定義。 就一個類而言,應該只有一個引起它變化的原因 這個說法不是很好懂,有一些抽象,不過呢,我們依舊可以嘗試著理解一下。 就一個類而言,只有一個引起它變化的原因,也就是說,除此之外,不能有其它引起變化的原因。 這樣就

大話設計模式單一職責原則

引用的3篇部落格,都很詳細的例子,這篇部落格是通過對參考內容的總結,便於自己理解,例子可以看參考的3篇部落格,這裡不寫 什麼是單一職責原則 單一職責原則:就一個類而言,應該僅有一個引起它變化的原因  簡單記憶:術業有專攻,我是專門搬磚的!!           

設計模式單一職責原則、開放-封閉原則以及依賴倒置原則

在設計程式碼中,我們有許多可以依照的設計模式,讓我把整個專案的邏輯結構變得清晰易於維護。當然,在設計模式中我們不只有各種模式,還有許多設計的原則,雖然他們不是程式碼架構的模板,但是這些原則卻時刻提醒我們提高程式碼質量和防止未來麻煩。這次我就將單一職責原則、開放-封閉原則以及依賴倒轉原則進行解釋。

深入淺出系列第一篇(設計模式單一職責原則)—— 從純小白到Java開發的坎坷經歷

各位看官大大們,晚上好。好久不見,我想死你們了...     先說說寫這個系列文章的背景: 工作了這麼久了,每天都忙著寫業務,好久沒有好好靜下心來好好總結總結了。正好這段時間公司組織設計模式的分享分,所以我才有機會在這裡和大家嘮嘮嗑。 也許因為自己是小白自學的吧,所以磕磕絆絆走了好多彎路。

西遊記之設計模式原則——單一職責原則

void 可能 equals main person 方法 隱患 客戶端代碼 p s 單一職責原則 ——專心致誌只做一件事 1 package danyizhize; 2 3 class SunWuKong { 4 public void XiangM

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

單一職責原則(Single Responsibility Principle) 定義:一個物件應該只包含單一的職責,並且該職責被完整地封裝在一個類中。即:不要存在多於一個導致類變更的原因。通俗的說,就是一個類只負責一項職責。 問題由來:類T負責兩個不同的職責:職責P1,職責

大話設計模式之四:1~5章(簡單工廠模式 、策略模式單一職責原則、開放封閉原則 、依賴倒轉原則

注:《大話設計模式》這本書很好的介紹了設計模式,其對應的原始碼是C#語言寫得,跑在visual studio上,所以自己先安裝visual studio ,然後將原始碼跑一跑,這樣能深刻的理解《大話設

面向對象設計原則 單一職責原則(Single responsibility principle)

敏捷軟件開發 實現邏輯 導致 五個 單獨 無法 dot 單一職責原則 其它 單一職責原則(SRP:Single responsibility principle)又稱單一功能原則,面向對象五個基本原則(SOLID)之一。 它規定一個類應該只有一個發生變化的原因。 該原則

軟體架構與模式(依賴注入 控制反轉 依賴倒置原則 開閉原則 單一職責原則 介面隔離原則 里氏代換原則)

名詞解釋:   依賴:  一個獨立元素的變化會影響到相關的元素   派生:  一個類是由其他類衍生出的,子類繼承了基類的結構(屬性的名詞和型別)方法   抽象:  去掉每個不重要的細節,專

六大設計原則——單一職責原則【Single Responsibility Principle】

宣告:本文內容是從網路書籍整理而來,並非原創。 使用者管理的例子 先看一張使用者管理的類圖: 再看一眼上面的圖,思考:這樣合理嗎? 這個介面是一個很糟糕的設計! 使用者的屬性和行為竟然混合在一起!!! 正確的做法是把使用者的資訊抽取成一個業務物件(Bu

設計原則-單一職責原則

1.定義    不要存在多餘一個導致類變更的原因,即一個類只負責一項職責。 2.問題由來    類T負責兩個不同的職責:職責P1,職責P2.當由於職責P1需求發生改變而需要修改類時,有可能導致原本執行正常的職責P2的功能發生故障3.解決方案    3.1分別建立T1和T2類完

設計模式單一職責

想要精通設計模式,必須要先搞清楚設計模式的六大原則。 在開始設計模式之前,先來談談設計模式的六大設計原則,第一個便是單一職責原則(Single Responsibility Principle)了。 單一職責原則定義 There should never

面向物件六大原則——單一職責原則

什麼是單一職責原則(Single Responsibility Principle, SRP)  在講解什麼是單一職責原則之前,我們先說一個例子,吊一下口味:我們在做專案的時候,會接觸到使用者,機構,角色管理這些模組,基本上使用的都是RBAC模型(Role-Ba

設計模式學習筆記(二) 設計基本原則之【單一職責原則

code 分享 開發者 實際應用 需要 ret ext file類 tor 單一職責原則(SRP: Single Responsibility Principle) 名詞解釋: 1) 職責:是指類變化的原因。 2) 職責擴散:就是因為某種原因,職責P被分化為粒度更細的職責P

設計模式六大原則(一):單一職責原則

控制 line 避免 多人 由來 pan 兩個類 思想 功能 單一職責定義: 不要存在多於一個導致類變更的原因,通俗的說,即一個類只負責一項職責。 問題由來: 類T負責兩個不同的職責:職責P1,職責P2。當由於職責P1需求發生改變而需要修改類T時,有可能會導致原

學習設計模式 - 六大基本原則單一職責原則

enc more ref 組合 代碼 aso HERE ali 不可   設計模式總共有六大基本原則,統稱為SOLID (穩定)原則,分別是S-單一職責原則(Single Responsibility Principle), O-開閉原則(Open closed Pri

[Python設計模式] 第3~5章 單一職責原則/開放-封閉原則/依賴倒轉原則

抽象類 內容 編寫 cat 過程 裏氏代換原則 數據庫連接 無需 維護 單一職責原則 就一個類而言,應該僅有一個引起它變化的原因。 如果一個類承擔的職責過多,就等於把這些職責耦合在一起,一個職責的變化可能會削弱或者抑制這個類完成其他職責的能力。這種耦合會導致脆弱的設計,當變

設計模式之六大設計原則之《一》魔性的單一職責原則

定義:單一職責原則,英文全稱Single Responsbility Property。怎樣的類設計才稱的上符合單一職責原則呢?一句話:應該有且僅有一個原因引起類的變更(There should never be more than one reason for a class to chang

【學習筆記】慕課網—Java設計模式精講 第3章 軟體設計七大原則-3-4 單一職責原則

/** * 軟體設計七大原則-單一職責原則 學習筆記 * @author cnRicky * @date 2018.11.10 */ 單一職責原則 定義:不要存在多於一個導致類變更的原因 一個類只負責一個職責,如果分別有兩個職責,那就建立兩個類分別負責職責1和職責2 一個類/介面/方法只負