摘要:設(shè)計(jì)原則梳理,參考核心技術(shù)與最佳實(shí)踐敏捷開發(fā)原則模式與實(shí)踐,文章面向?qū)ο笤O(shè)計(jì)的五大原則設(shè)計(jì)模式原則單一職責(zé)原則定義特性僅有一個(gè)引起類變化的原因一個(gè)類只承擔(dān)一項(xiàng)職責(zé)職責(zé)變化的原因避免相同的職責(zé)分散到不同的類,功能重復(fù)問題一個(gè)類承擔(dān)的職責(zé)過多,
PHP設(shè)計(jì)原則梳理,參考《PHP核心技術(shù)與最佳實(shí)踐》、《敏捷開發(fā)原則、模式與實(shí)踐》,文章PHP面向?qū)ο笤O(shè)計(jì)的五大原則、設(shè)計(jì)模式原則SOLID
單一職責(zé)原則(Single Responsibility Principle, SRP)僅有一個(gè)引起類變化的原因
一個(gè)類只承擔(dān)一項(xiàng)職責(zé)(職責(zé):變化的原因)
避免相同的職責(zé)分散到不同的類,功能重復(fù)
一個(gè)類承擔(dān)的職責(zé)過多,多個(gè)職責(zé)間相互依賴,一個(gè)職責(zé)的變換會影響這個(gè)類完成其他職責(zé)的能力,當(dāng)引起類變化的原因發(fā)生時(shí),會遭受到意想不到的破壞
減少類之間的耦合:當(dāng)需求變化時(shí),只修改一個(gè)類,從而隔離了變化帶來類對其他職責(zé)的影響
提高類的復(fù)用性:按需引用,一個(gè)類負(fù)責(zé)一個(gè)職責(zé),需求的變動只需要修改對應(yīng)的類或增加某一職責(zé)
降低類的復(fù)雜度:職責(zé)單一,功能分散開降低一個(gè)類多個(gè)職責(zé)類的復(fù)雜度
class ParseText { private $content; public function decodeText(String $content) { // TODO: decode content } public function saveText() { // TODO:: save $this->content; } } /* 問題思考: 解析的文本類型會有多種-html、xml、json 保存的文本也會有多種途徑-redis、mysql、file 客戶端只需要解析文本時(shí)必須會引入saveText不需要的方法 兩個(gè)職責(zé)之間沒有強(qiáng)烈的依賴關(guān)系存在 任意職責(zé)需求變化都需要更改這個(gè)類 */ /* 符合SRP的設(shè)計(jì) 職責(zé)拆分 */ class Decoder { private $content; public function decodeText(String $content) { // TODO: decode content } public function getText() { return $this->content; } } class Store { public function save($content) { // TODE: save } }
軟件設(shè)計(jì)所做的許多內(nèi)容就是發(fā)現(xiàn)職責(zé)并合理的分離職責(zé)間的關(guān)系。如果應(yīng)用程序的變化總是同時(shí)影響多個(gè)職責(zé),就沒必要分離職責(zé)。
接口隔離原則(Interface Segregation Principle ISP)設(shè)計(jì)應(yīng)用程序時(shí),類的接口不是內(nèi)聚的。不同的客戶端只包含集中的部分功能,但系統(tǒng)會強(qiáng)制客戶端實(shí)現(xiàn)模塊中所有方法,并且還要編寫一些啞方法。這樣的接口成為胖接口或者是接口污染,這樣的接口會給系統(tǒng)引入一些不當(dāng)?shù)男袨?,資源浪費(fèi),影響其他客戶端程序增強(qiáng)了耦合性等
ISP定義/特性不應(yīng)該強(qiáng)迫客戶端依賴與他們不需要的方法/功能
一個(gè)類對一個(gè)類的依賴應(yīng)該建立在最小的接口上
接口的實(shí)現(xiàn)類應(yīng)該只呈現(xiàn)為單一職責(zé)原則
將胖接口分離,每一組接口提供特定功能服務(wù)于特定一組的客戶端程序
對一組接口的更改不會/較小的影響到其他的接口/客戶端程序,保證接口的純潔性
解決方式胖接口分解成多個(gè)特定客戶端的接口/多重接口分離繼承
使用委托分離接口,兩個(gè)對象參與處理同一個(gè)請求,接受請求的對象將請求委托給另一個(gè)對象處理
/* * 公告接口 */ interface Employee { public function startWork(); public function endWork(); } /* * 定義特定客戶端接口 */ interface Coder { public function writeCode(); } interface Ui { public function designPage(); } class CoderClient implements Employee, Coder { public function startWork() { //TODO:: start work time } public function endWork() { //TODO:: end work time } public function writeCode() { //TODO:: start write code return "hellow world"; } } $c = new CoderClient(); echo $c->writeCode();
胖類會導(dǎo)致他們的客戶端程序之間產(chǎn)生不正常的并且有害的耦合關(guān)系。通過把胖客戶度分解成多個(gè)特定于客戶端的接口,客戶端緊緊依賴于他們實(shí)際調(diào)用的方法,從而解除了客戶端與他們沒有調(diào)用的方法之間的依賴關(guān)系。接口隔離應(yīng)做的小而少。
都是解決軟件設(shè)計(jì)中依賴關(guān)系原則
SRP 注重職責(zé)的劃分,主要約束類,其實(shí)是接口和方法,是程序中的細(xì)節(jié)和實(shí)現(xiàn)。ISP 注重接口的隔離,約束的是接口,從更宏觀的角度對接口的抽象設(shè)計(jì)
開放-封閉原則(Open-Close Principle OCP)隨著軟件系統(tǒng)規(guī)模的不斷擴(kuò)大,系統(tǒng)的維護(hù)和修改的復(fù)雜性不斷提高。系統(tǒng)一處的更改往往會影響到其他模塊。正確的運(yùn)用OCP原則可以解決此類問題。
一個(gè)模塊在擴(kuò)展行為方面應(yīng)該是開放的而在更改性方面應(yīng)該是封閉的
模塊的行為是可擴(kuò)展的,可以方便的對現(xiàn)有模塊的行為/功能進(jìn)行擴(kuò)展
對于模塊行為的擴(kuò)展不會/較小的影響現(xiàn)有系統(tǒng)/模塊
/* * 定義有固定行為的抽象接口 */ interface Process { public function action(String $content); } /* * 繼承抽象接口,擴(kuò)展不同的行為 */ class WriteToCache implements Process { public function action(String $content) { return "write content to cache: ".$content; } } class ParseText { private $content; public function decodeText($content) { $this->content = $content; } public function addAction(Process $process) { if ($process instanceof Process) { return $process->action($this->content); } } } $p = new ParseText(); $p->decodeText("content"); echo $p->addAction(new WriteToCache());
OCP核心思想就是抽象接口編程,抽象相對穩(wěn)定。讓類依賴與固定的抽象,通過面向?qū)ο蟮睦^承和多態(tài)讓類繼承抽象,復(fù)寫其方法或固有行為,是想新的擴(kuò)展方法/功能,實(shí)現(xiàn)擴(kuò)展。
里氏替換原則(Liskov Substitution Principle LSP)面向?qū)ο笾写罅康睦^承關(guān)系十分普遍和簡單,這種繼承規(guī)則是什么,最佳的繼承層次的規(guī)則又是什么,怎樣優(yōu)雅的設(shè)計(jì)繼承關(guān)系,子類能正確的對基類中的某些方法進(jìn)行重新,這是LSP原則所要處理的問題。
子類必須能夠替換掉他們的基類型:任何出現(xiàn)基類的地方都可以替換成子類并且客戶端程序不會改變基類行為或者出現(xiàn)異常和錯(cuò)誤,反之不行。
客戶端程序只應(yīng)該使用子類的抽象父類,這樣可以實(shí)現(xiàn)動態(tài)綁定(php多態(tài))
假設(shè)一個(gè)函數(shù)a,他的參數(shù)引用一個(gè)基類b,c是b的派生類,如果將c的對象作為b類型傳遞給a,會導(dǎo)致a出現(xiàn)錯(cuò)誤的行為,那沒c就違法了LSP原則。
/* * 基類 */ class Computer { public function action($a, $b) { return $a+$b; } } /* * 子類復(fù)習(xí)了父類方法,改變了action 的行為 * 違反了LSP原則 */ class Client extends Computer { public function action($a, $b) { return $a-$b; } } function run(Computer $computer, $a, $b) { return $computer->action($a, $b); } echo run((new Client()), 3, 5);
LSP是OCP得以應(yīng)用的最主要的原則之一,正是因?yàn)樽宇愋缘目商鎿Q行是的基類類型在無需修改的情況下擴(kuò)展功能。
依賴倒置原則(Depend Inversion Principle DIP)軟件開發(fā)設(shè)計(jì)中,總是傾向于創(chuàng)建一些高層模塊依賴底層模塊,底層模塊更改時(shí)直接影響到高層模塊,從而迫使他們改變。DIP原則描述了高層次模塊怎樣調(diào)用低層次模塊。
高層模塊不應(yīng)該依賴與底層模塊,二者都應(yīng)該依賴于抽象
抽象不應(yīng)該依賴與細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象
interface Arithmetic { //public function sub($a, $b); } class Client { public function computer(Arithmetic $arithmetic, $a, $b) { return $arithmetic->add($a, $b); } } class Addition implements Arithmetic { public function add($a, $b) { return $a + $b; } } $c = new Client(); echo $c->computer(new Addition(), 2, 3); /* client 高層類 依賴于Arithmetic,Addition底層實(shí)現(xiàn)細(xì)節(jié)類實(shí)現(xiàn)Arithmetic接口,達(dá)到二者依賴于抽象接口的DIP設(shè)計(jì)原則 */
DIP原則就是每個(gè)高層次模塊定義一個(gè)它所需服務(wù)的接口聲明,低層次模塊實(shí)現(xiàn)這個(gè)接口。每個(gè)高層次類通過該抽象接口使用服務(wù)。
思考面向?qū)ο筌浖_發(fā)中合理的遵循設(shè)計(jì)原則可以更好的設(shè)計(jì)代碼,減少不必要的錯(cuò)誤,提高程序的可維護(hù)性,可擴(kuò)展性和穩(wěn)定性。
單一職責(zé)(SRP)如何正確的劃分職責(zé),類的職責(zé)單一提高代碼復(fù)用性,降低耦合性
接口隔離(OCP)合理劃分接口功能,保證接口的專一性,純潔性,減少依賴關(guān)系
里氏替換(LSP)合理利用類的繼承體系,保證真確的繼承關(guān)系不被破壞
依賴倒置(DIP)抽象接口編程由于抽象具體實(shí)現(xiàn)
開放封閉(OCP)面向?qū)ο缶幊探K極目標(biāo)所達(dá)到的結(jié)果,類/模塊/系統(tǒng)的功能行為可擴(kuò)展,內(nèi)部更改性是封閉的
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/29018.html
摘要:面向?qū)ο笤O(shè)計(jì)的五大原則單一職責(zé)原則接口隔離原則開放封閉原則替換原則依賴倒置原則。主要是針對繼承的設(shè)計(jì)原則,繼承與派生多態(tài)是的主要特性。 面向?qū)ο笤O(shè)計(jì)的五大原則:單一職責(zé)原則、接口隔離原則、開放-封閉原則、替換原則、依賴倒置原則。這些原則主要是由Robert C.Martin在《敏捷軟件開發(fā)——原則、方法、與實(shí)踐》一書中總結(jié)出來,這五大原則也是23種設(shè)計(jì)模式的基礎(chǔ)。 單一職責(zé)原則 Sin...
摘要:過去一年時(shí)間寫了多篇文章來探討了我認(rèn)為的框架最核心部分的設(shè)計(jì)思路代碼實(shí)現(xiàn)。為了大家閱讀方便,我把這些源碼學(xué)習(xí)的文章匯總到這里。數(shù)據(jù)庫算法和數(shù)據(jù)結(jié)構(gòu)這些都是編程的內(nèi)功,只有內(nèi)功深厚了才能解決遇到的復(fù)雜問題。 過去一年時(shí)間寫了20多篇文章來探討了我認(rèn)為的Larave框架最核心部分的設(shè)計(jì)思路、代碼實(shí)現(xiàn)。通過更新文章自己在軟件設(shè)計(jì)、文字表達(dá)方面都有所提高,在剛開始決定寫Laravel源碼分析地...
摘要:前言本章我們要講解的是五大原則語言實(shí)現(xiàn)的第篇,里氏替換原則。因此,違反了里氏替換原則。與行為有關(guān),而不是繼承到現(xiàn)在,我們討論了和繼承上下文在內(nèi)的里氏替換原則,指示出的面向?qū)ο蟆? 前言 本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實(shí)現(xiàn)的第3篇,里氏替換原則LSP(The Liskov Substitution Principle )。英文原文:http://fre...
摘要:,開始我們的第一篇單一職責(zé)。通過解耦可以讓每個(gè)職責(zé)工更加有彈性地變化。關(guān)于本文本文轉(zhuǎn)自大叔的深入理解系列。深入理解系列文章,包括了原創(chuàng),翻譯,轉(zhuǎn)載,整理等各類型文章,原文是大叔的一個(gè)非常不錯(cuò)的專題,現(xiàn)將其重新整理發(fā)布。 前言 Bob大叔提出并發(fā)揚(yáng)了S.O.L.I.D五大原則,用來更好地進(jìn)行面向?qū)ο缶幊蹋宕笤瓌t分別是: The Single Responsibility Princi...
摘要:前言本章我們要講解的是五大原則語言實(shí)現(xiàn)的第篇,依賴倒置原則。當(dāng)應(yīng)用依賴倒置原則的時(shí)候,關(guān)系就反過來了。在當(dāng)靜態(tài)類型語言的上下文里討論依賴倒置原則的時(shí)候,耦合的概念包括語義和物理兩種。依賴倒置原則和依賴注入都是關(guān)注依賴,并且都是用于反轉(zhuǎn)。 前言 本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實(shí)現(xiàn)的第5篇,依賴倒置原則LSP(The Dependency Invers...
閱讀 2125·2021-09-29 09:35
閱讀 2003·2019-08-30 14:15
閱讀 3024·2019-08-30 10:56
閱讀 1014·2019-08-29 16:59
閱讀 634·2019-08-29 14:04
閱讀 1367·2019-08-29 12:30
閱讀 1085·2019-08-28 18:19
閱讀 562·2019-08-26 11:51