PHP 物件導向:設計模式之單例模式)

來源:互聯網
上載者:User

閱讀原文:http://www.yzswyl.cn/blread-1601.html

今天群裡有個朋友在問“private function __construct() {}”這樣能防止直接new對象嗎?於是呢我也去網上找了篇詳細的資料來分析下,感覺講的還是蠻不錯的,推薦給大家:

單例模式要解決的問題就是“如何讓這個類只有一個執行個體”。

我們的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 修飾的方法,可以不經執行個體化一個類就可以直接存取這個方法。

?
//不能用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 不是一個對象.";}?>

 程式運行結果為:

?
$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 不是一個對象.";}?>

程式運行結果為:

?
$a1 的類是 A , $a2 是 A$a1 $a2 指向同一對象.

到此,我們寫了一個最簡單的單例模式 。

現在,你可以嘗試寫一個應用單例設計模式的資料庫連接類。

要記住單例模式的使用效果和書寫方式。

閱讀原文:http://www.yzswyl.cn/blread-1601.html

今天群裡有個朋友在問“private function __construct() {}”這樣能防止直接new對象嗎?於是呢我也去網上找了篇詳細的資料來分析下,感覺講的還是蠻不錯的,推薦給大家:

單例模式要解決的問題就是“如何讓這個類只有一個執行個體”。

我們的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 修飾的方法,可以不經執行個體化一個類就可以直接存取這個方法。

?
//不能用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 不是一個對象.";}?>

 程式運行結果為:

?
$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 不是一個對象.";}?>

程式運行結果為:

?
$a1 的類是 A , $a2 是 A$a1 $a2 指向同一對象.

到此,我們寫了一個最簡單的單例模式 。

現在,你可以嘗試寫一個應用單例設計模式的資料庫連接類。

要記住單例模式的使用效果和書寫方式。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.