欧美人与禽2O2O性论交,秋霞免费视频,国产美女视频免费观看网址,国产成人亚洲综合网色欲网

軟件工程師需要理解的面向?qū)ο蟪绦蜷_發(fā)原則(ISP、DIP、LoD等)(面向?qū)ο筌浖こ涕_發(fā)分幾個階段)

導(dǎo)讀

本文示例使用C#語言寫的,但是原理適用與一切面向?qū)ο笳Z言。

其他幾個原則在這篇文章里:軟件工程師需要理解的面向?qū)ο蟪绦蜷_發(fā)原則(SRP、OCP、LSP)

1接口隔離原則(ISP)

定義

不應(yīng)該強迫客戶程序依賴并未使用的方法。接口不應(yīng)包含所有的對象行為,接口應(yīng)盡可能的小。這個原則用來處理“胖”接口所存在的缺點。

為什么要遵循此原則?

如果程序中的一部分更改會影響到程序中完全和它無關(guān)的其他部分,那么更改的代價和影響就變得不可預(yù)測。

違反原則的情形

接口污染,即接口被一個它不總是需要的方法污染,也就是說不是此接口的每一個派生類都需要那個方法。但由于接口已經(jīng)定義了這個方法,那么不需要它的派生類也要實現(xiàn)這個方法。

運用的方式方法

1)使用委托分離接口

對象的客戶端不通過該對象的接口去訪問它,而是通過委托去訪問他。此方案的缺點:委托處理會導(dǎo)致一些很小但仍然存在的運行時間和內(nèi)存的開銷。

2)使用多重繼承分離接口:通常這種做法是首選的。

運用與辨析

在web應(yīng)用開發(fā)中使用倉儲模式來封裝對底層數(shù)據(jù)庫的訪問,為此創(chuàng)建IRepository<T>接口:

public interface IRepository<T> { T GetById(int id); bool Delete(T entity); bool Save(T entity); void Update(T entity); IList<T> Get(string condition); …… }

這是一個典型的胖接口,并不是每一個子類都會實現(xiàn)這么多的方法。對于繼承了這個接口卻不需要實現(xiàn)其中某些方法的接口,只能將方法體設(shè)置為空實現(xiàn)或拋出異常。例如下面的類中不需要實現(xiàn)Get方法,所以在方法體中拋出了異常

public class MRepository<T> : IRepository<T> { public T GetById(int id) { //具體實現(xiàn) } public bool Delete(T entity) { //具體實現(xiàn) } public bool Save(T entity) { //具體實現(xiàn) } public void Update(T entity) { //具體實現(xiàn) } //不需要實現(xiàn)此方法 public IList<T> Get(string condition) { throw new NotImplementedException(); } }

在接口的實現(xiàn)里拋出異常,這樣做顯然違背了里氏替換原則(LSP),解決的辦法是將IRepository<T>拆分成兩個以上的更小的接口,按需實現(xiàn)接口,修改如下:

public interface IRepository<T> { T GetById(int id); bool Delete(T entity); bool Save(T entity); void Update(T entity); } public interface IRepositoryAL<T> { IList<T> Get(string condition); }public class MRepository<T> : IRepository<T> { public T GetById(int id) { //具體實現(xiàn) } public bool Delete(T entity) { //具體實現(xiàn) } public bool Save(T entity) { //具體實現(xiàn) } public void Update(T entity) { //具體實現(xiàn) } }

2依賴倒置原則(DIP)

定義

高層模塊不應(yīng)依賴于低層模塊。二者都應(yīng)依賴于抽象。抽象不應(yīng)該依賴于細節(jié),細節(jié)應(yīng)該依賴于抽象。這樣高層組件與低層組件之間通過抽象的接口來交換而不是具體類。該原則是框架設(shè)計的核心。

為什么要遵守此原則?

如果高層模塊依賴于低層模塊,那么對低層模塊的改動會直接影響到高層模塊,從而迫使他們一次做出改動。

違反原則的情形

高低層組件通過具體類來實現(xiàn)交互。

運用的方式方法

“倒置”不僅僅是依賴關(guān)系的倒置,也是接口所有權(quán)的倒置。當(dāng)使用DIP原則時,往往客戶擁有抽象接口,而他們的服務(wù)者則從這些抽象接口派生。

啟發(fā)式的方法:

1)找到那些指向具體類的引用的變量。

2)找到任何派生自具體類的類。

3)找到那些重寫方法,而基類方法已經(jīng)實現(xiàn)過了。

運用與辨析

依賴倒置式控制反轉(zhuǎn)的精髓,通過控制反轉(zhuǎn)可以深刻的體會到依賴倒置的作用。

3迪米特法則(LoD,又名最少知道原則)

定義

一個對象應(yīng)當(dāng)對其他對象有盡可能少的了解,只和自己關(guān)系最密切對象直接作用。

關(guān)系最密切的對象含義是:

當(dāng)前對象本身,通過該對象方法參數(shù)傳入的對象,此類的其他實例化對象,以及其所在聚集類的其他成員。

為什么要遵守此原則?

降低耦合,減少依賴。

違反原則的情形

和除了上述關(guān)系最密切的對象之間通信。

運用的方式方法

1)限制類及其成員的訪問權(quán)限。

2)引入門面模式和中介者模式。

4組合/聚合復(fù)用原則(CARP)

定義

將已有的多個對象組成一個新對象,達到復(fù)用的目的。

為什么要遵守此原則?

在建模的過程中,我們會發(fā)現(xiàn),某些實體之間不具有繼承關(guān)系,但是他們之間卻有一些像是的操作,為了實現(xiàn)這種無法用繼承表達的關(guān)系,我們遵照CARP原則。

5DRY原則(不要重復(fù)自己)

避免重復(fù)相同或相似的代碼。

運用與辨析

定義攔截器或過濾器充分體現(xiàn)了DRY原則。

例如使用ASP.NET MVC創(chuàng)建企業(yè)級應(yīng)用的過程中,定義了如下的控制器:

public class ExcludedDataController : BaseController{[HttpPost] public ActionResult Add(ExcludedDataInfo info) { if (Request.IsAjaxRequest()) { //其他代碼 } return new EmptyResult(); }public ActionResult Del(ExcludedDataInfo info) { if (Request.IsAjaxRequest()) { //其他代碼 } return new EmptyResult(); }public ActionResult BatchAdd(string itemCodes, int currentNavId, int library_DataBase_ID) { if (Request.IsAjaxRequest()) { //其他代碼 } return new EmptyResult(); }}

其中三個方法中都調(diào)用了Request.IsAjaxRequest()方法,明顯違反了DRY原則,解決的辦法是可以在控制器上添加攔截器。但是或許此控制器的操作中還有不被Ajax調(diào)用的操作,那么可以將這些操作移除,放入一個新的控制器中。

6控制反轉(zhuǎn)(IoC)

控制反轉(zhuǎn)是基于面向?qū)ο蟮脑瓌t,提倡松耦合理念的設(shè)計原則,允許獨立開發(fā)應(yīng)用程序的各個組件。

實現(xiàn)方式

實現(xiàn)方式有兩種:依賴注入,服務(wù)定位。

依賴注入引用其他的dll,組件之間的引用,一個類持有另一個類,這些都可以被看做是依賴。最常遇到的是一個類持有另一個類的問題。

依賴注入有三種方式:構(gòu)造函數(shù)注入,屬性注入,方法注入。最常使用的是構(gòu)造函數(shù)的注入。

服務(wù)定位通過IoC容器獲取依賴的具體類型,并將其賦給接口。

運用與辨析

記錄Entity Framework執(zhí)行SQL語句對優(yōu)化系統(tǒng)有極大的幫助。為記錄SQL定擴展命令攔截器IDbCommandInterceptor,在實現(xiàn)的方法中記錄SQL??梢詫QL記錄到本地文本文件中,也可以將SQL存儲到數(shù)據(jù)庫中,實現(xiàn)如下:

public class CommandInterceptor : IDbCommandInterceptor { private Logger logger = new Logger(); public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { this.logger.Log<int>(command, interceptionContext); } //其他方法…… }

上面的實現(xiàn)包含了一個依賴項,即Logger,如果后續(xù)改變存儲SQL的媒介,那么就要修改Logger.Log這個方法,明顯違反了OCP原則,也沒有遵循DIP原則。所以將其更改如下:

public class CommandInterceptor : IDbCommandInterceptor { private ICommandLogger logger; public CommandInterceptor(ICommandLogger logger) { this.logger = logger; } public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) { this.logger.Log<int>(command, interceptionContext); } //其他代碼 }

相關(guān)新聞

聯(lián)系我們
聯(lián)系我們
公眾號
公眾號
在線咨詢
分享本頁
返回頂部