java設計模式–七大原則詳解

設計模式

軟件設計模式(Design pattern),又稱設計模式,是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為瞭可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性、程序的重用性。

打個比方就像蓋大廈和小木屋,當功能簡單,函數和代碼少時,我們能較輕松的直接上手;但如果是像大廈那樣,功能復雜,需求可能變化且代碼量大時,我們就不能直接上手就來,需要像建築圖紙那樣提前規劃設計,那設計模式就像軟件(程序)的建築圖紙。

設計模式的目的是為瞭讓軟件(程序)具有更好的:

1.代碼重用性

相同功能的代碼,不用多次編寫,降低冗餘

2.可讀性

編程規范性, 便於其他程序員的閱讀和理解

3.可擴展性

當需要增加新的功能時,非常的方便,也稱為可維護性

4.可靠性

當我們增加新的功能後,對原來的功能沒有影響

5.使程序呈現高內聚,低耦合的特性

模塊內部緊密,但模塊間依賴小,一者出錯不影響他者

單一職責原則

單一職責原則(Single responsibility principle),即一個類應該隻負責一項職責。如類A負責兩個不同職責:職責1,職責2。當職責1需求變更而改變A時,可能造成職責2執行錯誤,所以需要將類A的粒度分解為A1、A2。

單一職責原則註意事項和細節

  • 降低類的復雜度,一個類隻負責一項職責。
  • 提高類的可讀性,可維護性
  • 降低變更引起的風險
  • 通常情況下,我們應當遵守單一職責原則,隻有邏輯足夠簡單,才可以在代碼級違反單一職責原則;隻有類中方法數量足夠少,可以在方法級別保持單一職責原則

在這裡插入圖片描述

接口隔離原則

接口隔離原則(Interface Segregation Principle),即客戶端不應該依賴它不需要的接口,即一個類對另一個類的依賴應該建立在最小的接口上。

比如:類A通過接口 I I I依賴類B,類C通過接口 I I I依賴類D,如果接口 I I I對於類A和類C來說不是最小接口,那麼類B和類D必須去實現他們不需要的方法。

在這裡插入圖片描述

按隔離原則應當這樣處理:將接口 I I I拆分為獨立的幾個接口,將類分別與他們需要的接口建立依賴關系,也就是采用接口隔離原則。

在這裡插入圖片描述

依賴倒轉原則

依賴倒轉原則(Dependence Inversion Principle),依賴倒轉(倒置)的中心思想是面向接口編程,所謂“倒轉”是指抽象不應該依賴細節,而是細節應該依賴抽象。也就是高層模塊不應該依賴低層模塊,二者都應該依賴其抽象。因為相對於細節的多變性,抽象的東西要穩定的多。

比如有個Person類,可以接受Email、QQ和微信的消息。如果都為其提供一個專門的方法,就會讓代碼非常的冗餘:

在這裡插入圖片描述

可以引入一個IReceiver接口,讓Person類依賴該接口。這樣QQ、微信和Email各自實現IReceiver裡面的方法即可:

在這裡插入圖片描述

裡氏替換原則

裡氏替換原則(Liskov Substitution Principle)要求所有引用基類的地方必須能透明地使用其子類的對象。也就是在繼承關系中,子類盡量不要重寫父類的方法。繼承實際上讓兩個類耦合性增強瞭,特別是運行多態比較頻繁的時,整個繼承體系的復用性會比較差。比如一種極端情況:一個類繼承瞭另一個類,但卻重寫瞭所有方法,那麼繼承的意義何在?說好的復用呢?

在這裡插入圖片描述

解決方法是把原來的父類和子類都繼承一個更通俗的基類,在適當的情況下,可以通過聚合,組合,依賴等來代替。

在這裡插入圖片描述

開閉原則

開閉原則(Open Closed Principle)一個軟件實體如類,模塊和函數應該對擴展開放(對提供方),對修改關閉(對使用方)。也就是當軟件需要變化時,盡量通過擴展軟件實體的行為來實現變化,而不是通過修改已有的代碼來實現變化。用抽象構建框架,用實現擴展細節。開閉原則是編程中最基礎、最重要的設計原則。編程中遵循其它原則,以及使用設計模式的目的就是遵循開閉原則。

舉個違反開閉原則的例子:

矩形Retangle和圓形Circle繼承瞭圖形類Shape(提供方),畫圖類GraphicEditor(使用方)會調用相關屬性。

在這裡插入圖片描述

但是如果再新增一個三角形,就要在使用方GraphicEditor新增對應方法,修改地方較多,違背開閉原則。

在這裡插入圖片描述

改進:把Shape做成抽象類並提供抽象方法draw,讓子類去實現即可。當新增圖形種類時,隻需讓新的圖形類繼承Shape,並實現draw方法即可。使用方的代碼就不需要修改,滿足開閉原則。

在這裡插入圖片描述

迪米特法則

迪米特法則(Demeter Principle)又叫最少知道原則,即一個類對自己依賴的類知道的越少越好,核心是降低類之間的耦合。也就是說,對於被依賴的類不管多麼復雜,都盡量將邏輯封裝在類的內部。對外除瞭提供的public 方法,不對外泄露任何信息。避免與非直接朋友的耦合,隻與直接的朋友通信,所謂的直接朋友是出現成員變量,方法參數,方法返回值中的類。而出現在局部變量中的類不是直接的朋友。也就是說,陌生的類最好不要以局部變量的形式出現在類的內部。

比如有學院員工類和學校員工類,然後各有一個管理類有可以獲取其所有員工,學校員工管理類有方法打印全部員工。

在這裡插入圖片描述

具體代碼:

void printAllEmployee(CollegeManager sub) {
		//獲取到學院員工
		List<CollegeEmployee> list1 = sub.getAllEmployee();
		System.out.println("---學院員工---");
		for (CollegeEmployee e : list1) {
			System.out.println(e.getId());
		}
		//獲取到學校總部員工
		List<Employee> list2 = this.getAllEmployee();
		System.out.println("---學校員工---");
		for (Employee e : list2) {
			System.out.println(e.getId());
		}
	}

分析SchoolManager類,發現Employee和CollegeManager都是它的直接朋友(出現在參數和返回值中),但CollegeEmployee不是直接朋友,是以局部變量的形式,違背瞭迪米特原則。

改進:避免依賴CollegeEmployee,封裝在CollegeManager中,對外提供public方法即可。

在這裡插入圖片描述

void printAllEmployee(CollegeManager sub) {
		sub.printEmployee();
		//獲取到學校總部員工
		List<Employee> list2 = this.getAllEmployee();
		System.out.println("---學校員工---");
		for (Employee e : list2) {
			System.out.println(e.getId());
		}
	}

合成復用原則

合成復用原則(Composite Reuse Principle)就是是盡量使用合成/聚合的方式,而不是使用繼承。

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

在這裡插入圖片描述

總結

設計原則核心思想

針對接口編程,把應用中可能需要變化的代碼和不需要變化的代碼分開獨立。都是為瞭交互對象間解耦合而操心。

本篇文章就到這裡瞭,希望能給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: