摘要:設計原則梳理,參考核心技術與最佳實踐敏捷開發原則模式與實踐,文章面向對象設計的五大原則設計模式原則單一職責原則定義特性僅有一個引起類變化的原因一個類只承擔一項職責職責變化的原因避免相同的職責分散到不同的類,功能重復問題一個類承擔的職責過多,
PHP設計原則梳理,參考《PHP核心技術與最佳實踐》、《敏捷開發原則、模式與實踐》,文章PHP面向對象設計的五大原則、設計模式原則SOLID
單一職責原則(Single Responsibility Principle, SRP)僅有一個引起類變化的原因
一個類只承擔一項職責(職責:變化的原因)
避免相同的職責分散到不同的類,功能重復
一個類承擔的職責過多,多個職責間相互依賴,一個職責的變換會影響這個類完成其他職責的能力,當引起類變化的原因發生時,會遭受到意想不到的破壞
減少類之間的耦合:當需求變化時,只修改一個類,從而隔離了變化帶來類對其他職責的影響
提高類的復用性:按需引用,一個類負責一個職責,需求的變動只需要修改對應的類或增加某一職責
降低類的復雜度:職責單一,功能分散開降低一個類多個職責類的復雜度
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 客戶端只需要解析文本時必須會引入saveText不需要的方法 兩個職責之間沒有強烈的依賴關系存在 任意職責需求變化都需要更改這個類 */ /* 符合SRP的設計 職責拆分 */ 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 } }
軟件設計所做的許多內容就是發現職責并合理的分離職責間的關系。如果應用程序的變化總是同時影響多個職責,就沒必要分離職責。
接口隔離原則(Interface Segregation Principle ISP)設計應用程序時,類的接口不是內聚的。不同的客戶端只包含集中的部分功能,但系統會強制客戶端實現模塊中所有方法,并且還要編寫一些啞方法。這樣的接口成為胖接口或者是接口污染,這樣的接口會給系統引入一些不當的行為,資源浪費,影響其他客戶端程序增強了耦合性等
ISP定義/特性不應該強迫客戶端依賴與他們不需要的方法/功能
一個類對一個類的依賴應該建立在最小的接口上
接口的實現類應該只呈現為單一職責原則
將胖接口分離,每一組接口提供特定功能服務于特定一組的客戶端程序
對一組接口的更改不會/較小的影響到其他的接口/客戶端程序,保證接口的純潔性
解決方式胖接口分解成多個特定客戶端的接口/多重接口分離繼承
使用委托分離接口,兩個對象參與處理同一個請求,接受請求的對象將請求委托給另一個對象處理
/* * 公告接口 */ 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();
胖類會導致他們的客戶端程序之間產生不正常的并且有害的耦合關系。通過把胖客戶度分解成多個特定于客戶端的接口,客戶端緊緊依賴于他們實際調用的方法,從而解除了客戶端與他們沒有調用的方法之間的依賴關系。接口隔離應做的小而少。
都是解決軟件設計中依賴關系原則
SRP 注重職責的劃分,主要約束類,其實是接口和方法,是程序中的細節和實現。ISP 注重接口的隔離,約束的是接口,從更宏觀的角度對接口的抽象設計
開放-封閉原則(Open-Close Principle OCP)隨著軟件系統規模的不斷擴大,系統的維護和修改的復雜性不斷提高。系統一處的更改往往會影響到其他模塊。正確的運用OCP原則可以解決此類問題。
一個模塊在擴展行為方面應該是開放的而在更改性方面應該是封閉的
模塊的行為是可擴展的,可以方便的對現有模塊的行為/功能進行擴展
對于模塊行為的擴展不會/較小的影響現有系統/模塊
/* * 定義有固定行為的抽象接口 */ interface Process { public function action(String $content); } /* * 繼承抽象接口,擴展不同的行為 */ 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核心思想就是抽象接口編程,抽象相對穩定。讓類依賴與固定的抽象,通過面向對象的繼承和多態讓類繼承抽象,復寫其方法或固有行為,是想新的擴展方法/功能,實現擴展。
里氏替換原則(Liskov Substitution Principle LSP)面向對象中大量的繼承關系十分普遍和簡單,這種繼承規則是什么,最佳的繼承層次的規則又是什么,怎樣優雅的設計繼承關系,子類能正確的對基類中的某些方法進行重新,這是LSP原則所要處理的問題。
子類必須能夠替換掉他們的基類型:任何出現基類的地方都可以替換成子類并且客戶端程序不會改變基類行為或者出現異常和錯誤,反之不行。
客戶端程序只應該使用子類的抽象父類,這樣可以實現動態綁定(php多態)
假設一個函數a,他的參數引用一個基類b,c是b的派生類,如果將c的對象作為b類型傳遞給a,會導致a出現錯誤的行為,那沒c就違法了LSP原則。
/* * 基類 */ class Computer { public function action($a, $b) { return $a+$b; } } /* * 子類復習了父類方法,改變了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得以應用的最主要的原則之一,正是因為子類性的可替換行是的基類類型在無需修改的情況下擴展功能。
依賴倒置原則(Depend Inversion Principle DIP)軟件開發設計中,總是傾向于創建一些高層模塊依賴底層模塊,底層模塊更改時直接影響到高層模塊,從而迫使他們改變。DIP原則描述了高層次模塊怎樣調用低層次模塊。
高層模塊不應該依賴與底層模塊,二者都應該依賴于抽象
抽象不應該依賴與細節,細節應該依賴于抽象
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底層實現細節類實現Arithmetic接口,達到二者依賴于抽象接口的DIP設計原則 */
DIP原則就是每個高層次模塊定義一個它所需服務的接口聲明,低層次模塊實現這個接口。每個高層次類通過該抽象接口使用服務。
思考面向對象軟件開發中合理的遵循設計原則可以更好的設計代碼,減少不必要的錯誤,提高程序的可維護性,可擴展性和穩定性。
單一職責(SRP)如何正確的劃分職責,類的職責單一提高代碼復用性,降低耦合性
接口隔離(OCP)合理劃分接口功能,保證接口的專一性,純潔性,減少依賴關系
里氏替換(LSP)合理利用類的繼承體系,保證真確的繼承關系不被破壞
依賴倒置(DIP)抽象接口編程由于抽象具體實現
開放封閉(OCP)面向對象編程終極目標所達到的結果,類/模塊/系統的功能行為可擴展,內部更改性是封閉的
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29018.html
摘要:面向對象設計的五大原則單一職責原則接口隔離原則開放封閉原則替換原則依賴倒置原則。主要是針對繼承的設計原則,繼承與派生多態是的主要特性。 面向對象設計的五大原則:單一職責原則、接口隔離原則、開放-封閉原則、替換原則、依賴倒置原則。這些原則主要是由Robert C.Martin在《敏捷軟件開發——原則、方法、與實踐》一書中總結出來,這五大原則也是23種設計模式的基礎。 單一職責原則 Sin...
摘要:過去一年時間寫了多篇文章來探討了我認為的框架最核心部分的設計思路代碼實現。為了大家閱讀方便,我把這些源碼學習的文章匯總到這里。數據庫算法和數據結構這些都是編程的內功,只有內功深厚了才能解決遇到的復雜問題。 過去一年時間寫了20多篇文章來探討了我認為的Larave框架最核心部分的設計思路、代碼實現。通過更新文章自己在軟件設計、文字表達方面都有所提高,在剛開始決定寫Laravel源碼分析地...
摘要:前言本章我們要講解的是五大原則語言實現的第篇,里氏替換原則。因此,違反了里氏替換原則。與行為有關,而不是繼承到現在,我們討論了和繼承上下文在內的里氏替換原則,指示出的面向對象。 前言 本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實現的第3篇,里氏替換原則LSP(The Liskov Substitution Principle )。英文原文:http://fre...
摘要:,開始我們的第一篇單一職責。通過解耦可以讓每個職責工更加有彈性地變化。關于本文本文轉自大叔的深入理解系列。深入理解系列文章,包括了原創,翻譯,轉載,整理等各類型文章,原文是大叔的一個非常不錯的專題,現將其重新整理發布。 前言 Bob大叔提出并發揚了S.O.L.I.D五大原則,用來更好地進行面向對象編程,五大原則分別是: The Single Responsibility Princi...
摘要:前言本章我們要講解的是五大原則語言實現的第篇,依賴倒置原則。當應用依賴倒置原則的時候,關系就反過來了。在當靜態類型語言的上下文里討論依賴倒置原則的時候,耦合的概念包括語義和物理兩種。依賴倒置原則和依賴注入都是關注依賴,并且都是用于反轉。 前言 本章我們要講解的是S.O.L.I.D五大原則JavaScript語言實現的第5篇,依賴倒置原則LSP(The Dependency Invers...
閱讀 2013·2021-09-29 09:35
閱讀 1948·2019-08-30 14:15
閱讀 2973·2019-08-30 10:56
閱讀 954·2019-08-29 16:59
閱讀 571·2019-08-29 14:04
閱讀 1300·2019-08-29 12:30
閱讀 1020·2019-08-28 18:19
閱讀 509·2019-08-26 11:51