日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
PHP代碼簡(jiǎn)潔之道——SOLID原則

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

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、雅安服務(wù)器托管、營(yíng)銷軟件、網(wǎng)站建設(shè)、盤錦網(wǎng)站維護(hù)、網(wǎng)站推廣。

  • S: 單一職責(zé)原則 (SRP)
  • O: 開(kāi)閉原則 (OCP)
  • L: 里氏替換原則 (LSP)
  • I: 接口隔離原則 (ISP)
  • D: 依賴反轉(zhuǎn)原則 (DIP)

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

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

Bad:

 
 
 
  1. class UserSettings{    
  2.     private $user;    
  3.     public function __construct($user)
  4.     {        
  5.         $this->user = $user;
  6.     }    
  7.     public function changeSettings($settings)
  8.     {        
  9.         if ($this->verifyCredentials()) {           
  10.          // ...
  11.         }
  12.     }    
  13.     private function verifyCredentials()
  14.     {        
  15.     // ...
  16.     }

Good:

 
 
 
  1. class UserAuth {    
  2. private $user;    
  3. public function __construct($user){        
  4.     $this->user = $user;
  5. }    
  6. public function verifyCredentials(){        
  7.     // ...
  8. }
  9. }
  10. class UserSettings {    
  11. private $user;    
  12. private $auth;    
  13. public function __construct($user) {        
  14.   $this->user = $user;        
  15.   $this->auth = new UserAuth($user);
  16. }    
  17. public function changeSettings($settings){        
  18.     if ($this->auth->verifyCredentials()) {            
  19.     // ...
  20.         }
  21.     }

開(kāi)閉原則 Open/Closed Principle (OCP)

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

Bad:

 
 
 
  1. abstract class Adapter{    
  2. protected $name;    
  3. public function getName(){        
  4.     return $this->name;
  5. }
  6. }
  7. class AjaxAdapter extends Adapter{    
  8. public function __construct(){     
  9.       parent::__construct();        
  10.       $this->name = 'ajaxAdapter';
  11.  }
  12. }
  13. class NodeAdapter extends Adapter{    
  14.     public function __construct(){   
  15.         parent::__construct();        
  16.         $this->name = 'nodeAdapter';
  17.     }
  18. }
  19.     class HttpRequester{    
  20.     private $adapter;    
  21.     public function __construct($adapter)
  22.     {        
  23.         $this->adapter = $adapter;
  24.     }    
  25.     public function fetch($url)
  26.     {
  27.         $adapterName = $this->adapter->getName();        
  28.     if ($adapterName === 'ajaxAdapter') {            
  29.         return $this->makeAjaxCall($url);
  30.         } 
  31.     elseif ($adapterName === 'httpNodeAdapter') {            
  32.         return $this->makeHttpCall($url);
  33.         }
  34.     }    
  35.     private function makeAjaxCall($url)
  36.     {        // request and return promise
  37.     }    
  38.     private function makeHttpCall($url)
  39.     {        // request and return promise
  40.     }

在上面的代碼中,對(duì)于HttpRequester類中的fetch方法,如果我新增了一個(gè)新的xxxAdapter類并且要在fetch方法中用到的話,就需要在HttpRequester類中去修改類(如加上一個(gè)elseif 判斷),而通過(guò)下面的代碼,就可很好的解決這個(gè)問(wèn)題。下面代碼很好的說(shuō)明了如何在不改變?cè)写a的情況下增加新功能。

Good:

 
 
 
  1. interface Adapter{    
  2.     public function request($url);
  3. }
  4.     class AjaxAdapter implements Adapter{    
  5.     public function request($url)
  6.     {        // request and return promise
  7.     }
  8. }
  9. class NodeAdapter implements Adapter{    
  10.     public function request($url)
  11.     {        // request and return promise
  12.     }
  13. }
  14.     class HttpRequester{    
  15.     private $adapter;    
  16.     public function __construct(Adapter $adapter)
  17.     {        $this->adapter = $adapter;
  18.     }    
  19.     public function fetch($url)
  20.     {        return $this->adapter->request($url);
  21.     }

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

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

Bad:

 
 
 
  1. class Rectangle{    
  2.     protected $width = 0;    
  3.     protected $height = 0;    
  4.     public function render($area)
  5.     {        // ...
  6.     }    
  7.     public function setWidth($width)
  8.     {        $this->width = $width;
  9.     }    
  10.     public function setHeight($height)
  11.     {        $this->height = $height;
  12.     }    
  13.     public function getArea()
  14.     {        return $this->width * $this->height;
  15.     }
  16. }
  17. class Square extends Rectangle{    
  18.     public function setWidth($width)
  19.     {        
  20.         $this->width = $this->height = $width;
  21.     }    
  22.     public function setHeight(height)
  23.     {        $this->width = $this->height = $height;
  24.     }
  25. }
  26. function renderLargeRectangles($rectangles){    
  27.     foreach ($rectangles as $rectangle) {
  28.         $rectangle->setWidth(4);
  29.         $rectangle->setHeight(5);
  30.         $area = $rectangle->getArea(); // BAD: Will return 25 for Square. Should be 20.
  31.         $rectangle->render($area);
  32.     }
  33. }
  34. $rectangles = 
  35. [new Rectangle(), new Rectangle(), new Square()];
  36. renderLargeRectangles($rectangles); 

Good:

 
 
 
  1. abstract class Shape{    
  2.     protected $width = 0;    
  3.     protected $height = 0;    
  4.     abstract public function getArea();    
  5.     public function render($area)    {        // ...
  6.     }
  7. }
  8. class Rectangle extends Shape{    
  9.     public function setWidth($width)
  10.     {        $this->width = $width;
  11.     }    
  12.     public function setHeight($height)
  13.     {        $this->height = $height;
  14.     }    
  15.     public function getArea()
  16.     {        return $this->width * $this->height;
  17.     }
  18. }
  19. class Square extends Shape{    
  20.     private $length = 0;    
  21.     public function setLength($length)
  22.     {        $this->length = $length;
  23.     }    
  24.     public function getArea()
  25.     {        return pow($this->length, 2);
  26.     }
  27. }
  28. function renderLargeRectangles($rectangles){    
  29. foreach ($rectangles as $rectangle) {        
  30. if ($rectangle instanceof Square) {
  31.             $rectangle->setLength(5);
  32.         } elseif ($rectangle instanceof Rectangle) {
  33.             $rectangle->setWidth(4);
  34.             $rectangle->setHeight(5);
  35.         }
  36.         $area = $rectangle->getArea(); 
  37.         $rectangle->render($area);
  38.     }
  39. }
  40. $shapes = [new Rectangle(), new Rectangle(), new Square()];
  41. renderLargeRectangles($shapes); 

接口隔離原則

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

有一個(gè)清晰的例子來(lái)說(shuō)明示范這條原則。當(dāng)一個(gè)類需要一個(gè)大量的設(shè)置項(xiàng),為了方便不會(huì)要求客戶端去設(shè)置大量的選項(xiàng),因?yàn)樵谕ǔK麄儾恍枰械脑O(shè)置項(xiàng)。使設(shè)置項(xiàng)可選有助于我們避免產(chǎn)生"胖接口"

Bad:

 
 
 
  1. interface Employee{    
  2.     public function work();    
  3.     public function eat();
  4. }
  5. class Human implements Employee{    
  6.     public function work()
  7.     {        // ....working
  8.     }    
  9.     public function eat()
  10.     {        // ...... eating in lunch break
  11.     }
  12. }class Robot implements Employee{    
  13.     public function work()
  14.     {        //.... working much more
  15.     }    
  16.     public function eat()
  17.     {        //.... robot can't eat, but it must implement this method
  18.     }

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

Good:

 
 
 
  1. interface Workable{    
  2.     public function work();
  3. }
  4. interface Feedable{    
  5.     public function eat();
  6. }
  7. interface Employee extends Feedable, Workable{
  8. }
  9. class Human implements Employee{    
  10.     public function work()
  11.     {        // ....working
  12.     }    
  13.     public function eat()
  14.     {        //.... eating in lunch break
  15.     }
  16. }// robot can only work
  17. class Robot implements Workable{    
  18.     public function work()
  19.     {        // ....working
  20.     }

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

這條原則說(shuō)明兩個(gè)基本的要點(diǎn):

  • 高階的模塊不應(yīng)該依賴低階的模塊,它們都應(yīng)該依賴于抽象
  • 抽象不應(yīng)該依賴于實(shí)現(xiàn),實(shí)現(xiàn)應(yīng)該依賴于抽象

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

Bad:

 
 
 
  1. class Employee{    
  2.     public function work()
  3.     {        // ....working
  4.     }
  5. }
  6. class Robot extends Employee{    
  7.     public function work()    {        //.... working much more
  8.     }
  9. }
  10. class Manager{    
  11.     private $employee;   
  12.     public function __construct(Employee $employee)
  13.     {        $this->employee = $employee;
  14.     }    public function manage()
  15.     {        $this->employee->work();
  16.     }

Good:

 
 
 
  1. interface Employee{   
  2.  public function work();
  3. }
  4.  class Human implements Employee{   
  5. public function work()
  6.     {        // ....working
  7.     }
  8. }
  9. class Robot implements Employee{    
  10. public function work()
  11.     {        //.... working much more
  12.     }
  13. }
  14. class Manager{    
  15. private $employee;    
  16. public function __construct(Employee $employee)
  17.     {        $this->employee = $employee;
  18.     }    public function manage()
  19.     {        $this->employee->work();
  20.     }

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

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

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

Bad:

 
 
 
  1. function showDeveloperList($developers){    
  2. foreach ($developers as $developer) {
  3.         $expectedSalary = 
  4. $developer->calculateExpectedSalary();
  5.         $experience = $developer->getExperience();
  6.         $githubLink = $developer->getGithubLink();
  7.         $data = [
  8.             $expectedSalary,
  9.             $experience,
  10.             $githubLink
  11.         ];
  12.         render($data);
  13.     }
  14. }
  15. function showManagerList($managers){    
  16. foreach ($managers as $manager) {
  17.         $expectedSalary = 
  18. $manager->calculateExpectedSalary();
  19.         $experience = $manager->getExperience();
  20.         $githubLink = $manager->getGithubLink();
  21.         $data = [
  22.             $expectedSalary,
  23.             $experience,
  24.             $githubLink
  25.         ];
  26.         render($data);
  27.     }

Good:

 
 
 
  1. function showList($employees){    
  2. foreach ($employees as $employee) {
  3.         $expectedSalary = 
  4. $employee->calculateExpectedSalary();
  5.         $experience = $employee->getExperience();
  6.         $githubLink = $employee->getGithubLink();
  7.         $data = [
  8.             $expectedSalary,
  9.             $experience,
  10.             $githubLink
  11.         ];
  12.         render($data);
  13.     }

Very good:

 
 
 
  1. function showList($employees){    foreach ($employees as $employee) {
  2.         render([
  3.             $employee->calculateExpectedSalary(),
  4.             $employee->getExperience(),
  5.             $employee->getGithubLink()
  6.         ]);
  7.     }

后記:雖然OOP設(shè)計(jì)需要遵守如上原則,不過(guò)實(shí)際的代碼設(shè)計(jì)一定要簡(jiǎn)單、簡(jiǎn)單、簡(jiǎn)單。在實(shí)際編碼中要根據(jù)情況進(jìn)行取舍,一味遵守原則,而不注重實(shí)際情況的話,可能會(huì)讓你的代碼變的難以理解!


當(dāng)前名稱:PHP代碼簡(jiǎn)潔之道——SOLID原則
當(dāng)前地址:http://www.5511xx.com/article/dhocioh.html