對於PHP物件導向設計五大原則(SOLID)的總結
這篇文章主要介紹了關於PHP物件導向設計五大原則(SOLID)的總結,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
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定義/特性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 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比較/* * 公告接口 */ 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 注重介面的隔離,約束的是接口,從更宏觀的角度對接口的抽象設計
- 一個模組在擴展行為方面應該是開放的而在更改性方面應該是封閉的
- 模組的行為是可擴展的,可以方便的對現有模組的行為/功能進行擴展
- 對於模組行為的擴充不會/較小的影響現有系統/模組
/*
* 定义有固定行为的抽象接口
*/
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核心想法就是抽象介面編程,抽象相對穩定。讓類別依賴與固定的抽象,透過物件導向的繼承和多態讓類別繼承抽象,複寫其方法或固有行為,是想新的擴展方法/功能,實現擴展。 ###/* * 定义有固定行为的抽象接口 */ 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());
里氏替换原则(Liskov Substitution Principle LSP)
问题
面向对象中大量的继承关系十分普遍和简单,这种继承规则是什么,最佳的继承层次的规则又是什么,怎样优雅的设计继承关系,子类能正确的对基类中的某些方法进行重新,这是LSP原则所要处理的问题。
定义/特性
子类必须能够替换掉他们的基类型:任何出现基类的地方都可以替换成子类并且客户端程序不会改变基类行为或者出现异常和错误,反之不行。
客户端程序只应该使用子类的抽象父类,这样可以实现动态绑定(php多态)
违反LSP原则
假设一个函数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)面向对象编程终极目标所达到的结果,类/模块/系统的功能行为可扩展,内部更改性是封闭的
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
以上是對於PHP物件導向設計五大原則(SOLID)的總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。
