SOLID 设计原则
SOLID 原則基本概念:
程序設(shè)計(jì)領(lǐng)域, SOLID (單一功能、開閉原則、里氏替換、接口隔離以及依賴反轉(zhuǎn))是由羅伯特·C·馬丁在21世紀(jì)早期 引入的記憶術(shù)首字母縮略字,指代了面向?qū)ο缶幊毯兔嫦驅(qū)ο笤O(shè)計(jì)的五個(gè)基本原則。當(dāng)這些原則被一起應(yīng)用時(shí),它們使得一個(gè)程序員開發(fā)一個(gè)容易進(jìn)行軟件維護(hù)和擴(kuò)展的系統(tǒng)變得更加可能SOLID被典型的應(yīng)用在測試驅(qū)動開發(fā)上,并且是敏捷開發(fā)以及自適應(yīng)軟件開發(fā)的基本原則的重要組成部分。
?
[S]?Single Responsibility Principle (單一功能原則)
單一功能原則 :單一功能原則 認(rèn)為對象應(yīng)該僅具有一種單一功能的概念。
換句話說就是讓一個(gè)類只做一種類型責(zé)任,當(dāng)這個(gè)類需要承擔(dān)其他類型的責(zé)任的時(shí)候,就需要分解這個(gè)類。在所有的SOLID原則中,這是大多數(shù)開發(fā)人員感到最能完全理解的一條。嚴(yán)格來說,這也可能是違反最頻繁的一條原則了。單一責(zé)任原則可以看作是低耦合、高內(nèi)聚在面向?qū)ο笤瓌t上的引申,將責(zé)任定義為引起變化的原因,以提高內(nèi)聚性來減少引起變化的原因。責(zé)任過多,可能引起它變化的原因就越多,這將導(dǎo)致責(zé)任依賴,相互之間就產(chǎn)生影響,從而極大的損傷其內(nèi)聚性和耦合度。單一責(zé)任,通常意味著單一的功能,因此不要為一個(gè)模塊實(shí) 現(xiàn)過多的功能點(diǎn),以保證實(shí)體只有一個(gè)引起它變化的原因。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
namespace SOLID {public class Users{/// <summary>/// 支付/// </summary>public void Pay(){}/// <summary>/// 數(shù)據(jù)庫操作/// </summary>public void DataAccess(){}/// <summary>/// 日志操作/// </summary>public void Logger(){}} }在這個(gè)用戶類中有這三個(gè)功能:1.支付邏輯,2數(shù)據(jù)庫邏輯,3.日志操作。如果將這三個(gè)功能結(jié)合在一個(gè)類中,可能會出現(xiàn)修改部分代碼時(shí)會破壞其他的部分。多個(gè)功能也使這個(gè)用戶類難以理解,降低了內(nèi)聚性。所以最好就是將這個(gè)類分離為三個(gè)分離的類,每個(gè)類僅僅有一個(gè)功能。
namespace SOLID {/// <summary>/// 數(shù)據(jù)庫操作/// </summary>class DataAccess { }/// <summary>/// 日志/// </summary>class Logger { }/// <summary>/// 支付/// </summary>class Pay { } }?
[o] Open Close Principle (開閉原則)
開閉原則(ocp) 認(rèn)為“軟件體應(yīng)該是對于擴(kuò)展開放的,但是對于修改封閉的”的概念。
軟件實(shí)體應(yīng)該是可擴(kuò)展,而不可修改的。也就是說,對擴(kuò)展是開放的,而對修改是封閉的。這個(gè)原則是諸多面向?qū)ο缶幊淘瓌t中最抽象、最難理解的一個(gè)。
對擴(kuò)展開放,意味著有新的需求或變化時(shí),可以對現(xiàn)有代碼進(jìn)行擴(kuò)展,以適應(yīng)新的情況。
對修改封閉,意味著類一旦設(shè)計(jì)完成,就可以獨(dú)立完成其工作,而不要對類進(jìn)行任何修改。
可以使用變化和不變來說明:封裝不變部分,開放變化部分,一般使用接口繼承實(shí)現(xiàn)方式來實(shí)現(xiàn)“開放”應(yīng)對變化,說大白話就是:你不是要變化嗎?,那么我就讓你繼承實(shí)現(xiàn)一個(gè)對象,用一個(gè)接口來抽象你的職責(zé),你變化越多,繼承實(shí)現(xiàn)的子類就越多。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
abstract class DataAccess{public abstract void OpenConnection();public abstract void CloseConnection();public abstract void ExecuteCommand();}/// <summary>/// SQL/// </summary>class SqlDataAccess : DataAccess{/// <summary>/// 打開SQL數(shù)據(jù)庫/// </summary>public override void OpenConnection(){}/// <summary>/// 關(guān)閉Sql數(shù)據(jù)連接/// </summary>public override void CloseConnection(){}/// <summary>/// 執(zhí)行Sql數(shù)據(jù)命令/// </summary>public override void ExecuteCommand(){}}/// <summary>/// ORACLE/// </summary>class OracleDataAccess : DataAccess{/// <summary>/// 打開Oracle數(shù)據(jù)連接/// </summary>public override void OpenConnection(){}/// <summary>/// 關(guān)閉Oracle數(shù)據(jù)連接/// </summary>public override void CloseConnection(){}/// <summary>/// 執(zhí)行Oracle數(shù)據(jù)命令/// </summary>public override void ExecuteCommand(){}}?
[L] Liskov Substitution Principle(里氏替換原則)
里氏替換原則 :里氏替換原則 認(rèn)為“程序中的對象應(yīng)該是可以在不改變程序正確性的前提下被它的子類所替換的”的概念。
軟件工程大師Robert C. Martin把里氏替換原則最終簡化為一句話:“Subtypes must be substitutable for their base types”。也就是,子類必須能夠替換成它們的基類。即:子類應(yīng)該可以替換任何基類能夠出現(xiàn)的地方,并且經(jīng)過替換以后,代碼還能正常工作。另外,不應(yīng)該 在代碼中出現(xiàn)if/else之類對子類類型進(jìn)行判斷的條件。里氏替換原則LSP是使代碼符合開閉原則的一個(gè)重要保證。正是由于子類型的可替換性才使得父類 型的模塊在無需修改的情況下就可以擴(kuò)展。在很多情況下,在設(shè)計(jì)初期我們類之間的關(guān)系不是很明確,LSP則給了我們一個(gè)判斷和設(shè)計(jì)類之間關(guān)系的基準(zhǔn):需不需 要繼承,以及怎樣設(shè)計(jì)繼承關(guān)系。
當(dāng)一個(gè)子類的實(shí)例應(yīng)該能夠替換任何其超類的實(shí)例時(shí),它們之間才具有is-A關(guān)系。繼承對于OCP,就相當(dāng)于多態(tài)性對于里氏替換原則。子類可以代替基類,客戶使用基類,他們不需要知道派生類所做的事情。這是一個(gè)針對行為職責(zé)可替代的原則,如果S是T的子類型,那么S對象就應(yīng)該在不改變?nèi)魏纬橄髮傩郧闆r下替換所有T對象。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
class Rectangle{protected int width = 0;protected int height = 0;public virtual void SetWidth(int width){this.width = width;}public virtual void SetHeight(int height){this.height = height;}public virtual int GetArea(){return this.width * this.height;}}class Square : Rectangle{public override void SetHeight(int height){this.height = height;this.width = height;}public override void SetWidth(int width){this.height = width;this.width = width;}}?
[I] Interface Segregation Principle(接口隔離原則)
接口隔離原則 :接口隔離原則 認(rèn)為“多個(gè)特定客戶端接口要好于一個(gè)寬泛用途的接口”的概念。?
不能強(qiáng)迫用戶去依賴那些他們不使用的接口。換句話說,使用多個(gè)專門的接口比使用單一的總接口總要好。注意:在代碼中應(yīng)用ISP并不一定意味著服務(wù)就是絕對安全的。仍然需要采用良好的編碼實(shí)踐,以確保正確的驗(yàn)證與授權(quán)。
這個(gè)原則起源于施樂公司,他們需要建立了一個(gè)新的打印機(jī)系統(tǒng),可以執(zhí)行諸如裝訂的印刷品一套,傳真多種任務(wù)。此系統(tǒng)軟件創(chuàng)建從底層開始編制,并實(shí)現(xiàn)了這些 任務(wù)功能,但是不斷增長的軟件功能卻使軟件本身越來越難適應(yīng)變化和維護(hù)。每一次改變,即使是最小的變化,有人可能需要近一個(gè)小時(shí)的重新編譯和重新部署。這 是幾乎不可能再繼續(xù)發(fā)展,所以他們聘請羅伯特Robert幫助他們。他們首先設(shè)計(jì)了一個(gè)主要類Job,幾乎能夠用于實(shí)現(xiàn)所有任務(wù)功能。只要調(diào)用Job類的 一個(gè)方法就可以實(shí)現(xiàn)一個(gè)功能,Job類就變動非常大,是一個(gè)胖模型啊,對于客戶端如果只需要一個(gè)打印功能,但是其他無關(guān)打印的方法功能也和其耦合,ISP 原則建議在客戶端和Job類之間增加一個(gè)接口層,對于不同功能有不同接口,比如打印功能就是Print接口,然后將大的Job類切分為繼承不同接口的子 類,這樣有一個(gè)Print Job類,等等。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ???
interface IDataAccess{void OpenConnection();void CloseConnection();}interface ISqlDataAccess : IDataAccess{void ExecuteSqlCommand();}interface IOracleDataAccess : IDataAccess{void ExecuteOracleCommand();}class SqlDataAccess : ISqlDataAccess{/// <summary>/// 執(zhí)行Sql數(shù)據(jù)命令/// </summary>public void ExecuteSqlCommand(){}/// <summary>/// 打開Sql數(shù)據(jù)連接/// </summary>public void OpenConnection(){}/// <summary>/// 關(guān)閉Sql數(shù)據(jù)連接/// </summary>public void CloseConnection(){}}class OracleDataAccess : IOracleDataAccess{/// <summary>/// 執(zhí)行Oracle數(shù)據(jù)命令/// </summary>public void ExecuteOracleCommand(){}/// <summary>/// 打開Oracle數(shù)據(jù)連接/// </summary>public void OpenConnection(){}/// <summary>/// 關(guān)閉Oracle數(shù)據(jù)連接/// </summary>public void CloseConnection(){}}?
[D] Dependency Inversion Principle(依賴反轉(zhuǎn)原則)
依賴反轉(zhuǎn)原則: 依賴反轉(zhuǎn)原則 認(rèn)為一個(gè)方法應(yīng)該遵從“依賴于抽象而不是一個(gè)實(shí)例” 的概念。依賴注入是該原則的一種實(shí)現(xiàn)方式。
依賴倒置原則(Dependency Inversion Principle,DIP)規(guī)定:代碼應(yīng)當(dāng)取決于抽象概念,而不是具體實(shí)現(xiàn)。
高層模塊不應(yīng)該依賴于低層模塊,二者都應(yīng)該依賴于抽象?
抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象?
類可能依賴于其他類來執(zhí)行其工作。但是,它們不應(yīng)當(dāng)依賴于該類的特定具體實(shí)現(xiàn),而應(yīng)當(dāng)是它的抽象。這個(gè)原則實(shí)在是太重要了,社會的分工化,標(biāo)準(zhǔn)化都 是這個(gè)設(shè)計(jì)原則的體現(xiàn)。顯然,這一概念會大大提高系統(tǒng)的靈活性。如果類只關(guān)心它們用于支持特定契約而不是特定類型的組件,就可以快速而輕松地修改這些低級 服務(wù)的功能,同時(shí)最大限度地降低對系統(tǒng)其余部分的影響。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?
interface IBankAccount{long BankNumber { get; set; } // 卡號decimal Balance { get; set; } // 余額}// 轉(zhuǎn)賬人interface ITransferSource : IBankAccount{void CutPayment(decimal value);}// 收款人interface ITransferDestination : IBankAccount{void AddMoney(decimal value);}class BankAccout : IBankAccount, ITransferSource, ITransferDestination{public long BankNumber { get; set; }public decimal Balance { get; set; }public void CutPayment(decimal value){Balance -= value;}public void AddMoney(decimal value){Balance += value;}}class TransferAmount{public decimal Amount { get; set; }public void Transfer(ITransferSource source, ITransferDestination dest){source.CutPayment(Amount);dest.AddMoney(Amount);}}參考于:
http://www.cnblogs.com/Ax0ne/p/3619481.html
http://www.cnblogs.com/shanyou/archive/2009/09/21/1570716.html
總結(jié)
以上是生活随笔為你收集整理的SOLID 设计原则的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ecs php mysql集成环境_在阿
- 下一篇: vts传感器采取船舶的_详解虎门大桥监测