溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

PHP中SOLID原則有哪些

發(fā)布時間:2021-11-02 10:59:43 來源:億速云 閱讀:156 作者:小新 欄目:編程語言

小編給大家分享一下PHP中SOLID原則有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

SOLID 是Michael Feathers推薦的便于記憶的首字母簡寫,它代表了Robert Martin命名的最重要的五個面對對象編碼設(shè)計原則:

  • S: 單一職責(zé)原則 (SRP)

  • O: 開閉原則 (OCP)

  • L: 里氏替換原則 (LSP)

  • I: 接口隔離原則 (ISP)

  • D: 依賴反轉(zhuǎn)原則 (DIP)

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

"修改一個類應(yīng)該只為一個理由"。人們總是易于用一堆方法塞滿一個類,如同我們在飛機上只能攜帶一個行李箱(把所有的東西都塞到箱子里)。這樣做的問題是:從概念上這樣的類不是高內(nèi)聚的,并且留下了很多理由去修改它。將你需要修改類的次數(shù)降低到最小很重要。這是因為,當(dāng)有很多方法在類中時,修改其中一處,你很難知曉在代碼庫中哪些依賴的模塊會被影響到。

Bad:

class UserSettings{         private $user;         public function __construct($user)     {                 $this->user = $user;     }         public function changeSettings($settings)     {                 if ($this->verifyCredentials()) {                     // ...         }     }         private function verifyCredentials()     {             // ...     } }

Good:

class UserAuth {     private $user;     public function __construct($user){             $this->user = $user; }     public function verifyCredentials(){             // ...  } } class UserSettings {     private $user;     private $auth;     public function __construct($user) {           $this->user = $user;           $this->auth = new UserAuth($user); }     public function changeSettings($settings){             if ($this->auth->verifyCredentials()) {                 // ...         }     } }

開閉原則 Open/Closed Principle (OCP)

正如Bertrand Meyer所述,"軟件的實體(類, 模塊,  函數(shù),等)應(yīng)該對擴展開放,對修改關(guān)閉。"這個原則是在說明應(yīng)該允許用戶在不改變已有代碼的情況下增加新的功能。

Bad:

abstract class Adapter{     protected $name;     public function getName(){             return $this->name; } } class AjaxAdapter extends Adapter{     public function __construct(){            parent::__construct();               $this->name = 'ajaxAdapter';  } } class NodeAdapter extends Adapter{         public function __construct(){            parent::__construct();                 $this->name = 'nodeAdapter';     } }     class HttpRequester{         private $adapter;         public function __construct($adapter)     {                 $this->adapter = $adapter;     }         public function fetch($url)     {         $adapterName = $this->adapter->getName();             if ($adapterName === 'ajaxAdapter') {                     return $this->makeAjaxCall($url);         }      elseif ($adapterName === 'httpNodeAdapter') {                     return $this->makeHttpCall($url);         }     }         private function makeAjaxCall($url)     {        // request and return promise     }         private function makeHttpCall($url)     {        // request and return promise     } }

在上面的代碼中,對于HttpRequester類中的fetch方法,如果我新增了一個新的xxxAdapter類并且要在fetch方法中用到的話,就需要在HttpRequester類中去修改類(如加上一個elseif  判斷),而通過下面的代碼,就可很好的解決這個問題。下面代碼很好的說明了如何在不改變原有代碼的情況下增加新功能。

Good:

interface Adapter{         public function request($url); }     class AjaxAdapter implements Adapter{         public function request($url)     {        // request and return promise     } } class NodeAdapter implements Adapter{         public function request($url)     {        // request and return promise     } }     class HttpRequester{         private $adapter;         public function __construct(Adapter $adapter)     {        $this->adapter = $adapter;     }         public function fetch($url)     {        return $this->adapter->request($url);     } }

里氏替換原則 Liskov Substitution Principle (LSP)

對這個概念***的解釋是:如果你有一個父類和一個子類,在不改變原有結(jié)果正確性的前提下父類和子類可以互換。這個聽起來讓人有些迷惑,所以讓我們來看一個經(jīng)典的正方形-長方形的例子。從數(shù)學(xué)上講,正方形是一種長方形,但是當(dāng)你的模型通過繼承使用了"is-a"的關(guān)系時,就不對了。

Bad:

class Rectangle{         protected $width = 0;         protected $height = 0;         public function render($area)     {        // ...     }         public function setWidth($width)     {        $this->width = $width;     }         public function setHeight($height)     {        $this->height = $height;     }         public function getArea()     {        return $this->width * $this->height;     } } class Square extends Rectangle{         public function setWidth($width)     {                 $this->width = $this->height = $width;     }         public function setHeight(height)     {        $this->width = $this->height = $height;     } } function renderLargeRectangles($rectangles){         foreach ($rectangles as $rectangle) {         $rectangle->setWidth(4);         $rectangle->setHeight(5);         $area = $rectangle->getArea(); // BAD: Will return 25 for Square. Should be 20.         $rectangle->render($area);     } }  $rectangles =  [new Rectangle(), new Rectangle(), new Square()]; renderLargeRectangles($rectangles);

Good:

abstract class Shape{         protected $width = 0;         protected $height = 0;         abstract public function getArea();         public function render($area)    {        // ...     } } class Rectangle extends Shape{         public function setWidth($width)     {        $this->width = $width;     }         public function setHeight($height)     {        $this->height = $height;     }         public function getArea()     {        return $this->width * $this->height;     } } class Square extends Shape{         private $length = 0;         public function setLength($length)     {        $this->length = $length;     }         public function getArea()     {        return pow($this->length, 2);     } } function renderLargeRectangles($rectangles){     foreach ($rectangles as $rectangle) {         if ($rectangle instanceof Square) {             $rectangle->setLength(5);         } elseif ($rectangle instanceof Rectangle) {             $rectangle->setWidth(4);             $rectangle->setHeight(5);         }          $area = $rectangle->getArea();          $rectangle->render($area);     } }  $shapes = [new Rectangle(), new Rectangle(), new Square()]; renderLargeRectangles($shapes);

接口隔離原則

接口隔離原則:"客戶端不應(yīng)該被強制去實現(xiàn)于它不需要的接口"。

有一個清晰的例子來說明示范這條原則。當(dāng)一個類需要一個大量的設(shè)置項,為了方便不會要求客戶端去設(shè)置大量的選項,因為在通常他們不需要所有的設(shè)置項。使設(shè)置項可選有助于我們避免產(chǎn)生"胖接口"

Bad:

interface Employee{         public function work();         public function eat(); } class Human implements Employee{         public function work()     {        // ....working     }         public function eat()     {        // ...... eating in lunch break     } }class Robot implements Employee{         public function work()     {        //.... working much more     }         public function eat()     {        //.... robot can't eat, but it must implement this method     } }

上面的代碼中,Robot類并不需要eat()這個方法,但是實現(xiàn)了Emplyee接口,于是只能實現(xiàn)所有的方法了,這使得Robot實現(xiàn)了它并不需要的方法。所以在這里應(yīng)該對Emplyee接口進行拆分,正確的代碼如下:

Good:

interface Workable{         public function work(); } interface Feedable{         public function eat(); } interface Employee extends Feedable, Workable{ } class Human implements Employee{         public function work()     {        // ....working     }         public function eat()     {        //.... eating in lunch break     } }// robot can only work  class Robot implements Workable{         public function work()     {        // ....working     } }

依賴反轉(zhuǎn)原則 Dependency Inversion Principle (DIP)

這條原則說明兩個基本的要點:

  • 高階的模塊不應(yīng)該依賴低階的模塊,它們都應(yīng)該依賴于抽象

  • 抽象不應(yīng)該依賴于實現(xiàn),實現(xiàn)應(yīng)該依賴于抽象

這條起初看起來有點晦澀難懂,但是如果你使用過php框架(例如  Symfony),你應(yīng)該見過依賴注入(DI)對這個概念的實現(xiàn)。雖然它們不是完全相通的概念,依賴倒置原則使高階模塊與低階模塊的實現(xiàn)細節(jié)和創(chuàng)建分離。可以使用依賴注入(DI)這種方式來實現(xiàn)它。更多的好處是它使模塊之間解耦。耦合會導(dǎo)致你難于重構(gòu),它是一種非常糟糕的的開發(fā)模式。

Bad:

class Employee{         public function work()     {        // ....working     } } class Robot extends Employee{         public function work()    {        //.... working much more     } } class Manager{         private $employee;        public function __construct(Employee $employee)     {        $this->employee = $employee;     }    public function manage()     {        $this->employee->work();     } }

Good:

interface Employee{     public function work(); }  class Human implements Employee{    public function work()     {        // ....working     } } class Robot implements Employee{     public function work()     {        //.... working much more     } } class Manager{     private $employee;     public function __construct(Employee $employee)     {        $this->employee = $employee;     }    public function manage()     {        $this->employee->work();     } }

別寫重復(fù)代碼 (DRY)

這條原則大家應(yīng)該都是比較熟悉了。

盡你***的努力去避免復(fù)制代碼,它是一種非常糟糕的行為,復(fù)制代碼通常意味著當(dāng)你需要變更一些邏輯時,你需要修改不止一處。

Bad:

function showDeveloperList($developers){     foreach ($developers as $developer) {         $expectedSalary =  $developer->calculateExpectedSalary();         $experience = $developer->getExperience();         $githubLink = $developer->getGithubLink();         $data = [             $expectedSalary,             $experience,             $githubLink         ];          render($data);     } } function showManagerList($managers){     foreach ($managers as $manager) {         $expectedSalary =  $manager->calculateExpectedSalary();         $experience = $manager->getExperience();         $githubLink = $manager->getGithubLink();         $data = [             $expectedSalary,             $experience,             $githubLink         ];          render($data);     } }

Good:

function showList($employees){     foreach ($employees as $employee) {         $expectedSalary =  $employee->calculateExpectedSalary();         $experience = $employee->getExperience();         $githubLink = $employee->getGithubLink();         $data = [             $expectedSalary,             $experience,             $githubLink         ];          render($data);     } }

Very good:

function showList($employees){    foreach ($employees as $employee) {         render([             $employee->calculateExpectedSalary(),             $employee->getExperience(),             $employee->getGithubLink()         ]);     } }

以上是“PHP中SOLID原則有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI