在本文中,您將了解如何實作單例設計模式,以及為什麼以及何時在應用程式中使用此模式。正如“Singleton”這個名字所暗示的那樣,這種方法允許我們創建一個類別的唯一一個物件。
讓我們看看維基百科上有關於此設計模式的內容:
單例模式是一種將類別的實例化限制為一個物件的設計模式。當只需要一個物件來協調整個系統的操作時,這非常有用。
如上文定義中所提到的,當我們想要確保任何類別都需要建立一個且僅有一個物件時,那麼我們應該為該類別實作 Singleton 模式。
p>
#你可能會問為什麼我們應該實作這樣一個類,它允許我們只創建它的一個物件。我想說,我們可以在很多用例中應用這種設計模式。其中包括:配置類別、會話類別、資料庫類別等等。
#本文中我將以資料庫類別為例。首先,我們將看看如果沒有為這樣的類別實作單例模式,會出現什麼問題。
想像一個非常簡單的資料庫連接類,一旦我們建立該類別的對象,它就會建立與資料庫的連接。
class database { private $dbName = null, $dbHost = null, $dbPass = null, $dbUser = null; public function __construct($dbDetails = array()) { $this->dbName = $dbDetails['db_name']; $this->dbHost = $dbDetails['db_host']; $this->dbUser = $dbDetails['db_user']; $this->dbPass = $dbDetails['db_pass']; $this->dbh = new PDO('mysql:host='.$this->dbHost.';dbname='.$this->dbName, $this->dbUser, $this->dbPass); } }
在上面的程式碼範例中,您可以看到,每次建立此類的物件時,它都會與資料庫建立連線。因此,如果開發人員在多個位置創建了此類的對象,想像一下它將與資料庫伺服器創建的(相同)資料庫連接的數量。
因此,開發人員在不知不覺中犯了錯誤,從而對資料庫和應用伺服器的速度產生了巨大影響。讓我們透過創建該類別的不同物件來看看同樣的事情。
$dbDetails = array( 'db_name' => 'designpatterns', 'db_host' => 'localhost', 'db_user' => 'root', 'db_pass' => 'mysqldba' ); $db1 = new database($dbDetails); var_dump($db1); $db2 = new database($dbDetails); var_dump($db2); $db3 = new database($dbDetails); var_dump($db3); $db4 = new database($dbDetails); var_dump($db4); // Output object(database)[1] private 'dbName' => string 'designpatterns' (length=14) private 'dbHost' => string 'localhost' (length=9) private 'dbPass' => string 'mysqldba' (length=8) private 'dbUser' => string 'root' (length=4) public 'dbh' => object(PDO)[2] object(database)[3] private 'dbName' => string 'designpatterns' (length=14) private 'dbHost' => string 'localhost' (length=9) private 'dbPass' => string 'mysqldba' (length=8) private 'dbUser' => string 'root' (length=4) public 'dbh' => object(PDO)[4] object(database)[5] private 'dbName' => string 'designpatterns' (length=14) private 'dbHost' => string 'localhost' (length=9) private 'dbPass' => string 'mysqldba' (length=8) private 'dbUser' => string 'root' (length=4) public 'dbh' => object(PDO)[6] object(database)[7] private 'dbName' => string 'designpatterns' (length=14) private 'dbHost' => string 'localhost' (length=9) private 'dbPass' => string 'mysqldba' (length=8) private 'dbUser' => string 'root' (length=4) public 'dbh' => object(PDO)[8]
如果你看到上面程式碼的輸出和輸出,你可以看到每個物件都分配了一個新的資源ID,所以所有物件都是全新的引用,因此它也分配單獨的記憶體。這樣不知不覺中我們的應用程式就會佔用實際上不需要的資源。
開發人員如何使用我們的基礎框架不在我們的控制範圍內。程式碼審查過程發生後,它就在我們的控制之下,但在開發過程中,我們不能一直站在他們身後。
為了克服這種情況,我們應該使我們的基類不能創建一個類別的多個物件;相反,它會給出一個已經創建的物件(如果有)。在這種情況下,我們應該考慮為我們的基類開發單例模式。
在實現此模式時,我們的目標是允許一次且僅建立一個類別的物件。請允許我添加下面的類別程式碼,然後我們將詳細介紹該類別的每個部分。
class database { private $dbName = null, $dbHost = null, $dbPass = null, $dbUser = null; private static $instance = null; private function __construct($dbDetails = array()) { // Please note that this is Private Constructor $this->dbName = $dbDetails['db_name']; $this->dbHost = $dbDetails['db_host']; $this->dbUser = $dbDetails['db_user']; $this->dbPass = $dbDetails['db_pass']; // Your Code here to connect to database // $this->dbh = new PDO('mysql:host='.$this->dbHost.';dbname='.$this->dbName, $this->dbUser, $this->dbPass); } public static function connect($dbDetails = array()) { // Check if instance is already exists if(self::$instance == null) { self::$instance = new database($dbDetails); } return self::$instance; } private function __clone() { // Stopping Clonning of Object } private function __wakeup() { // Stopping unserialize of object } }
幾乎沒有跡象表明上面的類別是 Singleton 類別。首先是私有建構函數,它防止使用 new 關鍵字建立物件。另一個指示是一個靜態成員變量,它保存對已建立物件的參考。
$dbDetails = array( 'db_name' => 'designpatterns', 'db_host' => 'localhost', 'db_user' => 'root', 'db_pass' => 'mysqldba' ); $db1 = database::connect($dbDetails); var_dump($db1); $db2 = database::connect($dbDetails); var_dump($db2); $db3 = database::connect($dbDetails); var_dump($db3); $db4 = database::connect($dbDetails); var_dump($db4); // Output object(database)[1] private 'dbName' => string 'designpatterns' (length=14) private 'dbHost' => string 'localhost' (length=9) private 'dbPass' => string 'mysqldba' (length=8) private 'dbUser' => string 'root' (length=4) public 'dbh' => object(PDO)[2] object(database)[1] private 'dbName' => string 'designpatterns' (length=14) private 'dbHost' => string 'localhost' (length=9) private 'dbPass' => string 'mysqldba' (length=8) private 'dbUser' => string 'root' (length=4) public 'dbh' => object(PDO)[2] object(database)[1] private 'dbName' => string 'designpatterns' (length=14) private 'dbHost' => string 'localhost' (length=9) private 'dbPass' => string 'mysqldba' (length=8) private 'dbUser' => string 'root' (length=4) public 'dbh' => object(PDO)[2] object(database)[1] private 'dbName' => string 'designpatterns' (length=14) private 'dbHost' => string 'localhost' (length=9) private 'dbPass' => string 'mysqldba' (length=8) private 'dbUser' => string 'root' (length=4) public 'dbh' => object(PDO)[2]
如果比較兩個部分的輸出,那麼您將看到,在單例模式的輸出中,所有不同物件的物件資源 ID 都是相同的。但不使用設計模式時並非如此。
由於各種原因,這種設計模式也稱為反模式,我將在下面提到:
我盡力解釋了網路上廣泛討論的單例設計模式。我希望這篇文章對您有幫助。我們已經介紹了該模式的兩個方面,即設計模式和反模式。
#請在下面發表您的意見、建議和/或問題,我會盡快回覆。您也可以透過 Twitter @XpertDevelopers 聯繫我或直接給我發電子郵件。
#以上是單例模式:專為提高效率而設計的詳細內容。更多資訊請關注PHP中文網其他相關文章!