您的位置:首頁 >  新聞中心 > 行業(yè)動(dòng)態(tài)
  行業(yè)動(dòng)態(tài)
 

PHP代碼簡(jiǎn)潔之道——SOLID原則

來源:原創(chuàng)    時(shí)間:2017-10-24    瀏覽:0 次

SOLID 是Michael Feathers引薦的便于回憶的首字母簡(jiǎn)寫,它代表了Robert Martin命名的最重要的五個(gè)面臨目標(biāo)編碼規(guī)劃準(zhǔn)則
S: 單一責(zé)任準(zhǔn)則 (SRP)
O: 開閉準(zhǔn)則 (OCP)
L: 里氏替換準(zhǔn)則 (LSP)
I: 接口阻隔準(zhǔn)則 (ISP)
D: 依靠回轉(zhuǎn)準(zhǔn)則 (DIP)
單一責(zé)任準(zhǔn)則 Single Responsibility Principle (SRP)
"修正一個(gè)類應(yīng)該只為一個(gè)理由"。人們總是易于用一堆辦法塞滿一個(gè)類,好像我們?cè)陲w機(jī)上只能帶著一個(gè)行李箱(把一切的東西都塞到箱子里)。這樣做的問題是:從概念上這樣的類不是高內(nèi)聚的,而且留下了許多理由去修正它。將你需求修正類的次數(shù)降低到最小很重要。這是由于,當(dāng)有許多辦法在類中時(shí),修正其間一處,你很難知曉在代碼庫中哪些依靠的模塊會(huì)被影響到。

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()) {            
    // ...
        }
    }
}
開閉準(zhǔn)則 Open/Closed Principle (OCP)
正如Bertrand Meyer所述,"軟件的實(shí)體(類, 模塊, 函數(shù),等)應(yīng)該對(duì)擴(kuò)展敞開,對(duì)修正封閉。"這個(gè)準(zhǔn)則是在闡明應(yīng)該答應(yīng)用戶在不改動(dò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
    }
}
在上面的代碼中,關(guān)于HttpRequester類中的fetch辦法,如果我新增了一個(gè)新的xxxAdapter類而且要在fetch辦法中用到的話,就需求在HttpRequester類中去修正類(如加上一個(gè)elseif 判別),而經(jīng)過下面的代碼,就可很好的處理這個(gè)問題。下面代碼很好的闡明了如安在不改動(dòng)原有代碼的狀況下添加新功用。
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);
    }
}
里氏替換準(zhǔn)則 Liskov Substitution Principle (LSP)
對(duì)這個(gè)概念最好的解說是:如果你有一個(gè)父類和一個(gè)子類,在不改動(dòng)原有成果正確性的前提下父類和子類能夠交換。這個(gè)聽起來讓人有些利誘,所以讓我們來看一個(gè)經(jīng)典的正方形-長(zhǎng)方形的比如。從數(shù)學(xué)上講,正方形是一種長(zhǎng)方形,可是當(dāng)你的模型經(jīng)過承繼運(yùn)用了"is-a"的聯(lián)系時(shí),就不對(duì)了。
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);
接口阻隔準(zhǔn)則
接口阻隔準(zhǔn)則:"客戶端不該該被強(qiáng)制去完成于它不需求的接口"。
有一個(gè)明晰的比如來闡明演示這條準(zhǔn)則。當(dāng)一個(gè)類需求一個(gè)很多的設(shè)置項(xiàng),為了便利不會(huì)要求客戶端去設(shè)置很多的選項(xiàng),由于在一般他們不需求一切的設(shè)置項(xiàng)。使設(shè)置項(xiàng)可選有助于我們防止發(fā)生"胖接口"
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()這個(gè)辦法,可是完成了Emplyee接口,所以只能完成一切的辦法了,這使得Robot完成了它并不需求的辦法。所以在這里應(yīng)該對(duì)Emplyee接口進(jìn)行拆分,正確的代碼如下:
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)準(zhǔn)則 Dependency Inversion Principle (DIP)
這條準(zhǔn)則闡明兩個(gè)根本的關(guān)鍵:
高階的模塊不該該依靠低階的模塊,它們都應(yīng)該依靠于籠統(tǒng)
籠統(tǒng)不該該依靠于完成,完成應(yīng)該依靠于籠統(tǒng)
這條起先看起來有點(diǎn)不流暢難明,可是如果你運(yùn)用過php結(jié)構(gòu)(例如 Symfony),你應(yīng)該見過依靠注入(DI)對(duì)這個(gè)概念的完成。盡管它們不是徹底相通的概念,依靠倒置準(zhǔn)則使高階模塊與低階模塊的完成細(xì)節(jié)和創(chuàng)立別離。能夠運(yùn)用依靠注入(DI)這種方法來完成它。更多的優(yōu)點(diǎn)是它使模塊之間解耦。耦合會(huì)導(dǎo)致你難于重構(gòu),它是一種十分糟糕的的開發(fā)形式。
Bad:
class Employee{    
    public function work()

免费视频观无码一区,国内精品一区二区无码,99精品无码视频在线播放,ā片国产在线播放