面向對象設計(OOD)核心原則讓我的程式子產品達到“高内聚低耦合”,這是來自于30年前興起的結構化設計(structured Design),但是同樣适用于我們的OOD。
1.高内聚:
高内聚是指某個特定子產品(程式,類型)都應完成一系列相關功能,描述了不同程式,類型中方法,方法中不同操作描述的邏輯之間的距離相近。高内聚意味可維護性,可重新性,因為子產品對外部的依賴少(功能的完備性)。如果兩個子產品之間的修改,互不影響這說明子產品之間是高内聚的。子產品的内聚和其擔當的職責成反比,即,子產品的職責越多,子產品的内聚性越低,這也是子產品的單一原則(SRP),SRP提倡每個類型都最好隻承擔單一的職責,隻有單一的改變因素。
2.低耦合:
耦合是描述子產品之間的依賴程度,如果一個子產品的修改,都有影響另一個子產品則,兩子產品之間是互相依賴耦合的。(依賴具有傳遞性,耦合的兩個子產品可能間接依賴),低耦合是我們的設計目的,但不是不存在耦合不存依賴,依賴是必須的,因為子產品之間必須通信互動,不過我的設計依賴應該依賴于不變或者不易變的接口,無需了解子產品的具實作(OO封裝性)。
在面向對象:我們可以簡述為功能完備(高内聚)的對象之間的互動是依賴于不變或不易變的接口契約(低耦合)。
實作高内聚低耦合:行之有效的方式是分了關注點(SOC),将系統拆分成功能不同沒有重疊功能集。每個功能隻關注一個方面(Aspect)保證子產品之間功能沒有或者盡量少的重複。子產品化内部實作細節隐藏,隻暴露必須的接口,使得子產品之間依賴于抽象,達到穩定。分離關注點的思想存在于我們軟體設計的各個領域。如在.net的世界裡SOA(面向服務架構)服務就是關注點,隻暴露出必要的契約。分層架構從邏輯上利用接口抽象資訊隐藏,減少依賴。MVC,MVP也是遵循分了關注點原則,達到表現層和邏輯的分離。
面向對象設計原則:
1.降低耦合度:對象直接需要互動,這就存在依賴,為了實作低耦合就必須減少依賴,依賴于穩定或不易變抽象。考慮如下訂單日志記錄場景:我們需要在訂單每部操作記錄更改日志。
public class OrderManager
{
public void Create(Order order)
{
//訂單處理.
Logger log = new Logger();
var history=GetHistory();
log.log(history);
}
在這裡我們的OrderManager和Logger存在高耦合,Logger類的修改可能導緻OrderManager的修改,而且不能随意切換我們的日志記錄方式,比如檔案,控制台,資料庫等日志方式。
面向抽象程式設計提出抽象(接口,abstract類)是不易變的穩定抽象;對于OrderManager來說我不需要了解日志記錄元件内部,隻需要明白提供那些接口可用,怎麼用。
public interface ILogger
void Log(History history);
public class Logger
public void Log(History history)
//内部實作
};
那麼我們可以從設計模式工廠模式(工廠模式是負責一些列相似對象的建立)Create 日志元件ILogger。
我們的OrderManager 就可以實作為:
ILogger log =LoggerFactory.Create();
log.Log(history);
這樣我們的OrderManager就依賴于ILogger,而隔離Logger具體實作,将依賴于抽象,把變化縮小到Factory内部(同樣也可以用抽象工廠),如果日志實作變化我們可以重新實作ILogger ,修改Factory邏輯,如果内部利用配置我的需求變更轉移到配置。這就是面向對象第一原則,依賴于抽象而隐藏實作。(利用IOC是一種更好的方式)
2.代碼的重用性:盡量保證相同功能代碼隻出現一次(Code once run anywhere)。代碼的重用在面對對象設計中有繼承群組合兩種方式,一般推薦組合優先。組合依賴于接口,組合更安全,易于維護,測試。繼承存在父類通路權限,父類的修改導緻子類的變化,太多的繼承也有導緻派生類的膨脹,維護管理也是件頭痛的事。
3.開閉原則(OCP):表述擁抱需求變化,盡量做到對子產品的擴充開發,修改關閉。對于新增需求我們完美的做法是新增類型而不是修改邏輯,這就意味着我們必須使用組合或者是繼承體系(為了避免上一條重用性,我的繼承應該是幹淨的繼承體系,派生類應該隻是新增功能而不是修改來自父類上下文),
4.裡氏替換(LSP):表述派生類應該可以在任何地方替代父類使用。并不是所有的子類都可以完全替換子類,比如設計父類私有上下文資訊的通路,導緻子類無法通路。
5.依賴倒置(DIP):描述元件之間高層元件不應該依賴于底層元件。依賴倒置是指實作和接口倒置,采用自頂向下的方式關注所需的底層元件接口,而不是其實作。DI架構實作IOC(控制反轉)就是DIP很好的插入底層元件構造架構(分構造注入,函數注入,屬性注入)。微軟Unity,Castle windsor,Ninject等架構支援。
本文轉自 破狼 51CTO部落格,原文連結:http://blog.51cto.com/whitewolfblog/856563,如需轉載請自行聯系原作者