2020久久超碰欧美精品最新亚洲欧美日韩久久精品,国产福利电影一区二区三区,亚洲欧美日韩一区在线观看,亚洲国产欧美日韩欧美特级,亚洲欧美日韩成人一区久久,欧美日韩精品一区二区三区不卡,国产欧美日韩va另类影音先锋,亚洲欧美日韩久久精品,亚洲欧美日韩国产成人精品影院,亚洲国产欧美日韩精品一区二区三区,欧美日韩国产成人高清视频,日韩久久精品国产免费观看频道,久久人人爽人人爽从片av高清,国产精品综合一区二区

首頁新聞動態正文

PHP面向對象:設計模式[單例模式]

更新時間:2018-11-29 來源:黑馬程序員技術社區 瀏覽量:

單件模式要解決的問題就是“如何讓這個類只有一個實例”。
我們的web應用中,大量使用了數據庫連接,如果反復建立與數據庫的連接必然消耗更多的系統資源。
我們如何解決這個問題,建立唯一的數據庫連接是必要的方式。
我們又如何知道與這個數據庫的連接是否已經建立? 還是需要現在建立?
單件模式可以解決這個問題。
先假設我們需要一個類完成在內存中只有一份的功能,我們該如何做呢?
我們一步一步的使用前面學過的知識來寫一個單件的例子。

前面學過,每次用 new 類名 的方式,就可以創建一個對象。我們必須禁止外部程序用 new 類名的方式來創建多個實例。
解決辦法是:我們將構造函數設置成 private ,讓構造函數只能在內部被調用,而外部不能調用。這樣,這個類就不能被外部用 new 的方式建立多個實例了。

以下是不能被外部用new實例化的類。

<?
class A{
    private function __construct(){}
}

$a = new A();
?>

程序運行結果為:
Fatal error: Call to private A::__construct() from invalid context in E:\PHPProjects\test.php on line 6
我們已經禁止外部用new實例化這個類,我們改如何讓用戶訪問這個類呢?前門堵了,我們需要給用戶留個后門。
解決辦法是:static 修飾的方法,可以不經實例化一個類就可以直接訪問這個方法。

<?
class A{
    private function __construct(){}

    static function getClassA(){
        return "這里是后門,可以通過這里進入類內部..";
    }
}

echo A::getClassA();
?>

程序運行結果為:

這里是后門,可以通過這里進入類內部..

雖然我們已經進入類內部,但我們要的是這個類的唯一實例?先不管別的,我們先需要一個實例。通過這個static的方法返回這個實例,如何做呢?
解決辦法是:private的構造函數,不能被外部實例化。但是我們已經成功潛入類的內部了(間諜?007?),我們在內部當然可以調用private的方法創建對象。我們這樣做看看。
下面的例子我們確實返回了A類的實例,但注意兩次執行返回的不是同一個實例。

//不能用new實例化的類.<br>
//static的方法留給外部訪問.<br>
//在方法內部返回實例.<br><br>

<?
class A{
    private function __construct(){}
    static function getClassA(){
        $a = new A();
        return $a;
    }
}

// 看到這里確實返回的是 A 的實例.但不是同一個對象.
$a1 = A::getClassA();
$a2 = A::getClassA();
echo "\$a1 的類是 ".get_class($a1)." , \$a2 是 ".get_class($a1);
if($a1 === $a2){
   echo "<br> \$a1 \$a2 指向同一對象.";
}else{
   echo "<br> \$a1 \$a2 不是一個對象.";
}
?>

程序運行結果為:

//不能用new實例化的類.
//static的方法留給外部訪問.
//在方法內部返回實例.

$a1 的類是 A , $a2 是 A
$a1 $a2 不是一個對象.
我們已經通過static方法返回了A的實例。但還有問題。我們如何保證我們多次操作獲得的是同一個實例的呢?
解決辦法:static的屬性在內部也只有一個。static 屬性能有效的被靜態方法調用。將這個屬性也設置成private,以防止外部調用。先將這個屬性設置成 null。每次返回對象前,先判斷這個屬性是否為 null 。如果為 null 就創建這個類的新實例,并賦值給這個 static 屬性。如果不為空,就返回這個指向實例的 static 屬性。

//不能用new實例化的類.<br>
//static的方法留給外部訪問.<br>
//在方法內部返回實例.<br>
//定義靜態屬性保證這個實例能被靜態方法調用.<br>
//增加判斷部分.<br><br>

<?
class A{
    private static $a = null;
    private function __construct(){}
    static function getClassA(){
        if( null == self::$a){
            self::$a = new A();
        }
        return self::$a;
    }
}
// 看到這里確實返回的是 A 的實例.但不是同一個對象.
$a1 = A::getClassA();
$a2 = A::getClassA();
echo "\$a1 的類是 ".get_class($a1)." , \$a2 是 ".get_class($a1);
if($a1 === $a2){
   echo "<br> \$a1 \$a2 指向同一對象.";
}else{
   echo "<br> \$a1 \$a2 不是一個對象.";
}
?>

程序運行結果為:

//不能用new實例化的類.
//static的方法留給外部訪問.
//在方法內部返回實例.
//定義靜態屬性保證這個實例能被靜態方法調用.
//增加判斷部分.

$a1 的類是 A , $a2 是 A
$a1 $a2 指向同一對象.
到此,我們寫了一個最簡單的 單件模式 。
現在,你可以嘗試寫一個應用單件設計模式的數據庫連接類。
要記住單件模式的使用效果和書寫方式。

作者:黑馬程序員PHP+H5全棧培訓學院

首發: http://java.itheima.com







分享到:
在線咨詢 我要報名
和我們在線交談!