成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

PHP面向?qū)ο笤O(shè)計的五個基準(zhǔn)原則是什么

這篇文章主要介紹“PHP面向?qū)ο笤O(shè)計的五個基準(zhǔn)原則是什么”的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強(qiáng),希望這篇“PHP面向?qū)ο笤O(shè)計的五個基準(zhǔn)原則是什么”文章能幫助大家解決問題。

網(wǎng)站建設(shè)公司,為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計及定制網(wǎng)站建設(shè)服務(wù),專注于成都定制網(wǎng)頁設(shè)計,高端網(wǎng)頁制作,對成都除甲醛等多個行業(yè)擁有豐富的網(wǎng)站建設(shè)經(jīng)驗的網(wǎng)站建設(shè)公司。專業(yè)網(wǎng)站設(shè)計,網(wǎng)站優(yōu)化推廣哪家好,專業(yè)seo優(yōu)化排名優(yōu)化,H5建站,響應(yīng)式網(wǎng)站。

S.O.L.I.D面向?qū)ο笤O(shè)計(OOD)的 5 個準(zhǔn)則的首字母縮寫,這些準(zhǔn)則是由 Robert C. Martin 提出的, 他更為人所熟知的名字是 Uncle Bob。

這些準(zhǔn)則使得開發(fā)出易擴(kuò)展、可維護(hù)的軟件變得更容易。也使得代碼更精簡、易于重構(gòu)。同樣也是敏捷開發(fā)和自適應(yīng)軟件開發(fā)的一部分。

S.O.L.I.D 意思是:

擴(kuò)展出來的首字母縮略詞看起來可能很復(fù)雜,實際上它們很容易理解。

  • S- 單一功能原則

  • O- 開閉原則

  • L- 里氏替換原則

  • I- 接口隔離原則

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

接下來讓我們看看每個原則,來了解為什么 S.O.L.I.D 可以幫助我們成為更好的開發(fā)人員。

單一職責(zé)原則

縮寫是 S.R.P,該原則內(nèi)容是:

一個類有且只能有一個因素使其改變,意思是一個類只應(yīng)該有單一職責(zé).

例如,假設(shè)我們有一些圖形,并且想要計算這些圖形的總面積.是的,這很簡單對不對?

class Circle {
    public $radius;

    public function __construct($radius) {
        $this->radius = $radius;
    }
}

class Square {
    public $length;

    public function __construct($length) {
        $this->length = $length;
    }
}

首先,我們創(chuàng)建圖形類,該類的構(gòu)造方法初始化必要的參數(shù).接下來,創(chuàng)建AreaCalculator類,然后編寫計算指定圖形總面積的邏輯代碼.

class AreaCalculator {

    protected $shapes;

    public function __construct($shapes = array()) {
        $this->shapes = $shapes;
    }

    public function sum() {
        // logic to sum the areas
    }

    public function output() {
        return 'Sum of the areas of provided shapes: ' . $this->sum();
    }
}

AreaCalculator使用方法,我們只需簡單的實例化這個類,并且傳遞一個圖形數(shù)組,在頁面底部展示輸出內(nèi)容.

$shapes = array(
    new Circle(2),
    new Square(5),
    new Square(6)
);

$areas = new AreaCalculator($shapes);

echo $areas->output();

輸出方法的問題在于,AreaCalculator處理了數(shù)據(jù)輸出邏輯.因此,假如用戶希望將數(shù)據(jù)以 json 或者其他格式輸出呢?

所有邏輯都由 AreaCalculator類處理,這恰恰違反了單一職責(zé)原則(SRP); AreaCalculator類應(yīng)該只負(fù)責(zé)計算圖形的總面積,它不應(yīng)該關(guān)心用戶是想要json還是HTML格式數(shù)據(jù)。

因此,要解決這個問題,可以創(chuàng)建一個 SumCalculatorOutputter類,并使用它來處理所需的顯示邏輯,以處理所有圖形的總面積該如何顯示。

SumCalculatorOutputter類的工作方式如下:

$shapes = array(
    new Circle(2),
    new Square(5),
    new Square(6)
);

$areas = new AreaCalculator($shapes);
$output = new SumCalculatorOutputter($areas);

echo $output->JSON();
echo $output->HAML();
echo $output->HTML();
echo $output->JADE();

現(xiàn)在,無論你想向用戶輸出什么格式數(shù)據(jù),都由 SumCalculatorOutputter類處理。

開閉原則

對象和實體應(yīng)該對擴(kuò)展開放,但是對修改關(guān)閉.

簡單的說就是,一個類應(yīng)該不用修改其自身就能很容易擴(kuò)展其功能.讓我們看一下 AreaCalculator類,特別是 sum方法.

public function sum() {
    foreach($this->shapes as $shape) {
        if(is_a($shape, 'Square')) {
            $area[] = pow($shape->length, 2);
        } else if(is_a($shape, 'Circle')) {
            $area[] = pi() * pow($shape->radius, 2);
        }
    }

    return array_sum($area);
}

如果我們想用 sum方法能計算更多圖形的面積,我們就不得不添加更多的 if/else blocks,然而這違背了開閉原則.

讓這個 sum方法變得更好的方式是將計算每個形狀面積的代碼邏輯移出 sum 方法,將其放進(jìn)各個形狀類中:

class Square {
    public $length;

    public function __construct($length) {
        $this->length = $length;
    }

    public function area() {
        return pow($this->length, 2);
    }
}

相同的操作應(yīng)該被用來處理 Circle類,  在類中添加一個 area方法。  現(xiàn)在,計算任何形狀面積之和應(yīng)該像下邊這樣簡單:

public function sum() {
    $area = [];
    foreach($this->shapes as $shape) {
        $area[] = $shape->area();
    }

    return array_sum($area);
}

接下來我們可以創(chuàng)建另一個形狀類并在計算總和時傳遞它而不破壞我們的代碼。 然而現(xiàn)在又出現(xiàn)了另一個問題,我們怎么能知道傳入  AreaCalculator的對象實際上是一個形狀,或者形狀對象中有一個 area方法?

接口編碼是實踐 S.O.L.I.D的一部分,例如下面的例子中我們創(chuàng)建一個接口類,每個形狀類都會實現(xiàn)這個接口類:

interface ShapeInterface {
    public function area();
}

class Circle implements ShapeInterface {
    public $radius;

    public function __construct($radius) {
        $this->radius = $radius;
    }

    public function area() {
        return pi() * pow($this->radius, 2);
    }
}

在我們的 AreaCalculator的 sum 方法中,我們可以檢查提供的形狀類的實例是否是 ShapeInterface的實現(xiàn),否則我們就拋出一個異常:

public function sum() {
    $area = [];
    foreach($this->shapes as $shape) {
        if(is_a($shape, 'ShapeInterface')) {
            $area[] = $shape->area();
            continue;
        }

        throw new AreaCalculatorInvalidShapeException;
    }

    return array_sum($area);
}

里氏替換原則

如果對每一個類型為 T1的對象 o1,都有類型為 T2 的對象o2,使得以 T1定義的所有程序 P 在所有的對象 o1 都代換成 o2 時,程序 P 的行為沒有發(fā)生變化,那么類型 T2 是類型 T1 的子類型。

這句定義的意思是說:每個子類或者衍生類可以毫無問題地替代基類/父類。

依然使用 AreaCalculator類, 假設(shè)我們有一個 VolumeCalculator類,這個類繼承了  AreaCalculator類:

class VolumeCalculator extends AreaCalulator {
    public function construct($shapes = array()) {
        parent::construct($shapes);
    }

    public function sum() {
        // logic to calculate the volumes and then return and array of output
        return array($summedData);
    }
}

SumCalculatorOutputter類:

class SumCalculatorOutputter {
    protected $calculator;

    public function __constructor(AreaCalculator $calculator) {
        $this->calculator = $calculator;
    }

    public function JSON() {
        $data = array(
            'sum' => $this->calculator->sum();
        );

        return json_encode($data);
    }

    public function HTML() {
        return 'Sum of the areas of provided shapes: ' . $this->calculator->sum();
    }
}

如果我們運(yùn)行像這樣一個例子:

$areas = new AreaCalulator($shapes);
$volumes = new VolumeCalculator($solidShapes);

$output = new SumCalculatorOutputter($areas);
$output2 = new SumCalculatorOutputter($volumes);

程序不會出問題, 但當(dāng)我們使用$output2對象調(diào)用 HTML方法時 ,我們接收到一個 E_NOTICE錯誤,提示我們 數(shù)組被當(dāng)做字符串使用的錯誤。

為了修復(fù)這個問題,只需:

public function sum() {
    // logic to calculate the volumes and then return and array of output
    return $summedData;
}

而不是讓VolumeCalculator類的 sum 方法返回數(shù)組。

$summedData 是一個浮點數(shù)、雙精度浮點數(shù)或者整型。

接口隔離原則

使用方(client)不應(yīng)該依賴強(qiáng)制實現(xiàn)不使用的接口,或不應(yīng)該依賴不使用的方法。

繼續(xù)使用上面的 shapes 例子,已知擁有一個實心塊,如果我們需要計算形狀的體積,我們可以在 ShapeInterface中添加一個方法:

interface ShapeInterface {
    public function area();
    public function volume();
}

任何形狀創(chuàng)建的時候必須實現(xiàn) volume方法,但是【平面】是沒有體積的,實現(xiàn)這個接口會強(qiáng)制的讓【平面】類去實現(xiàn)一個自己用不到的方法。

ISP原則不允許這么去做,所以我們應(yīng)該創(chuàng)建另外一個擁有 volume 方法的SolidShapeInterface 接口去代替這種方式,這樣類似立方體的實心體就可以實現(xiàn)這個接口了:

interface ShapeInterface {
    public function area();
}

interface SolidShapeInterface {
    public function volume();
}

class Cuboid implements ShapeInterface, SolidShapeInterface {
    public function area() {
        //計算長方體的表面積
    }

    public function volume() {
        // 計算長方體的體積
    }
}

這是一個更好的方式,但是要注意提示類型時不要僅僅提示一個 ShapeInterfaceSolidShapeInterface
你能創(chuàng)建其它的接口,比如 ManageShapeInterface,并在平面和立方體的類上實現(xiàn)它,這樣你能很容易的看到有一個用于管理形狀的api。例:

interface ManageShapeInterface {
    public function calculate();
}

class Square implements ShapeInterface, ManageShapeInterface {
    public function area() { /Do stuff here/ }

    public function calculate() {
        return $this->area();
    }
}

class Cuboid implements ShapeInterface, SolidShapeInterface, ManageShapeInterface {
    public function area() { /Do stuff here/ }
    public function volume() { /Do stuff here/ }

    public function calculate() {
        return $this->area() + $this->volume();
    }
}

現(xiàn)在在 AreaCalculator類中,我們可以很容易地用 calculate替換對area方法的調(diào)用,并檢查對象是否是 ManageShapeInterface的實例,而不是 ShapeInterface

依賴倒置原則

最后,但絕不是最不重要的:

實體必須依賴抽象而不是具體的實現(xiàn).即高等級模塊不應(yīng)該依賴低等級模塊,他們都應(yīng)該依賴抽象.

這也許聽起來讓人頭大,但是它很容易理解.這個原則能夠很好的解耦,舉個例子似乎是解釋這個原則最好的方法:

class PasswordReminder {
    private $dbConnection;

    public function __construct(MySQLConnection $dbConnection) {
        $this->dbConnection = $dbConnection;
    }
}

首先 MySQLConnection是低等級模塊,然而 PasswordReminder是高等級模塊,但是根據(jù) S.O.L.I.D. 中 D的解釋:依賴于抽象而不依賴與實現(xiàn), 上面的代碼段違背了這一原則,因為 PasswordReminder類被強(qiáng)制依賴于 MySQLConnection類.

稍后,如果你希望修改數(shù)據(jù)庫驅(qū)動,你也不得不修改 PasswordReminder類,因此就違背了 Open-close principle

PasswordReminder類不應(yīng)該關(guān)注你的應(yīng)用使用了什么數(shù)據(jù)庫,為了進(jìn)一步解決這個問題,我們「面向接口寫代碼」,由于高等級和低等級模塊都應(yīng)該依賴于抽象,我們可以創(chuàng)建一個接口:

interface DBConnectionInterface {
    public function connect();
}

這個接口有一個連接數(shù)據(jù)庫的方法,MySQLConnection類實現(xiàn)該接口,在 PasswordReminder的構(gòu)造方法中不要直接將類型約束設(shè)置為 MySQLConnection類,而是設(shè)置為接口類,這樣無論你的應(yīng)用使用什么類型的數(shù)據(jù)庫,PasswordReminder類都能毫無問題地連接數(shù)據(jù)庫,且不違背 開閉原則

class MySQLConnection implements DBConnectionInterface {
    public function connect() {
        return "Database connection";
    }
}

class PasswordReminder {
    private $dbConnection;

    public function __construct(DBConnectionInterface $dbConnection) {
        $this->dbConnection = $dbConnection;
    }
}

從上面一小段代碼,你現(xiàn)在能看出高等級和低等級模塊都依賴于抽象了。

關(guān)于“PHP面向?qū)ο笤O(shè)計的五個基準(zhǔn)原則是什么”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,小編每天都會為大家更新不同的知識點。

分享文章:PHP面向?qū)ο笤O(shè)計的五個基準(zhǔn)原則是什么
URL地址:http://jinyejixie.com/article26/gdpejg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、網(wǎng)站建設(shè)微信小程序、動態(tài)網(wǎng)站、全網(wǎng)營銷推廣、自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)
环江| 布拖县| 威远县| 芦溪县| 郴州市| 达州市| 荔浦县| 确山县| 山东省| 宜兰市| 宾阳县| 望都县| 连平县| 丹东市| 宜良县| 高阳县| 岳西县| 宝丰县| 韩城市| 溧阳市| 韶山市| 甘肃省| 久治县| 浑源县| 沁源县| 湾仔区| 伊通| 阿克陶县| 龙口市| 延吉市| 海伦市| 白沙| 曲松县| 雅江县| 马尔康县| 桂林市| 凌源市| 宁强县| 周宁县| 太保市| 金湖县|