對於PHP物件導向設計五大原則(SOLID)的總結

來源:互聯網
上載者:User
這篇文章主要介紹了關於對PHP物件導向設計五大原則(SOLID)的總結,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下

PHP設計原則梳理,參考《PHP核心技術與最佳實務》、《敏捷開發原則、模式與實踐》,文章PHP物件導向設計的五大原則、設計模式原則SOLID

單一職責原則(Single Responsibility Principle, SRP)

定義/特性
  • 僅有一個引起類變化的原因

  • 一個類只承擔一項職責(職責:變化的原因)

  • 避免相同的職責分散到不同的類,功能重複

問題
  • 一個類承擔的職責過多,多個職責間相互依賴,一個職責的變換會影響這個類完成其他職責的能力,當引起類變化的原因發生時,會遭受到意想不到的破壞

遵守SPR原則優勢
  • 減少類之間的耦合:當需求變化時,只修改一個類,從而隔離了變化帶來類對其他職責的影響

  • 提高類的複用性:按需引用,一個類負責一個職責,需求的變動只需要修改對應的類或增加某一職責

  • 降低類的複雜度:職責單一,功能分散開降低一個類多個職責類的複雜度

程式碼範例
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定義/特性

  • 不應該強迫用戶端依賴與他們不需要的方法/功能

  • 一個類對一個類的依賴應該建立在最小的介面上

  • 介面的實作類別應該只呈現為單一職責原則

遵循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比較
  • 都是解決軟體設計中依賴關係原則

  • SRP 注重職責的劃分,主要約束類,其實是介面和方法,是程式中的細節和實現。ISP 注重介面的隔離,約束的是介面,從更宏觀的角度對介面的抽象設計

開放-封閉原則(Open-Close Principle OCP)

問題

隨著軟體系統規模的不斷擴大,系統的維護和修改的複雜性不斷提高。系統一處的更改往往會影響到其他模組。正確的運用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多態)

違反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)物件導向編程終極目標所達到的結果,類/模組/系統的功能行為可擴充,內部更改性是封閉的

以上就是本文的全部內容,希望對大家的學習有所協助,更多相關內容請關注topic.alibabacloud.com!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.