Analysis on the single-instance mode of php single-state design model

Source: Internet
Author: User
Tags constructor

1. Meaning of the single-state design model:

The main function of the single-state mode is to ensure that only one instance object exists in a class in the object-oriented programming design. As the object creation mode, the singleton mode ensures that a class has only one instance, and the instance is self-instantiated and global to the entire system. It does not create instance copies, but returns a reference to the instance stored in the singleton class.

2. Three key points of a single mode:

① A static member variable is required to save the unique instance of the class;
② Constructor and clone functions must be declared as private, so as to prevent external programs from losing the meaning of the Singleton mode;
③ A public static method (usually the getInstance method) must be provided to access this instance to return a reference of a unique instance.

 

The code is as follows: Copy code
<? Php
Class DB {
Private static $ obj = null; // declare a private, static member attribute $ obj
Private function _ construct () {// private constructor. The object can only be instantiated within the class.
Echo "database connected <br> ";
}
Public static function getInstance () {// This static method can be used to obtain objects of this class.
If (is_null (self: $ obj) // if $ obj in this class is empty, it indicates that it has not been instantiated.
Self: $ obj = new self (); // instantiate this class object
Return self: $ obj; // return the object of this class
}
Public function query ($ SQL) {// execute an SQL statement to complete database operations
Echo $ SQL;
}
}
$ Db = DB: getInstance (); // You can only use the static method getInstance () to obtain the database class objects.
$ Db-> query ("select * from user"); // access the members in the object
?>

 

In Singleton mode, only one instance exists for an object. It also provides a global access point (usually a static getInstance method) for the unique instance ). The Singleton mode is widely used, for example:
Database operation object
Log writing object
Configure resolution objects globally
The common feature of these scenarios is that, in terms of business logic, objects are modified during the operation.

Only one instance is required

New instances increase unnecessary resource consumption.

Convenient global call
.

The following three aspects are described respectively:

1. Only one instance is required for the business

Take the database connection object as an example. Join a shopping website with a MySQL database
127.0.0.1: 3306
In a process, we only need to connect to the database once no matter how many operations we need to change the database, and use the same database Connection handle (MySQL Connection Resource ), from the perspective of business needs, only one instance is needed.

On the contrary, taking a shopping website as an example, there are many items, which are different (id, name, price...). In this case, you need to display a list of items and add them to create
Product
As a data ing object, an instance cannot meet the business needs because each product is different.

2. Keep new operations to increase unnecessary resource consumption


We usually perform some business operations in the class constructor (the new operation will certainly be called, for example, the database connection object may try to read the database configuration in the constructor and connect to the database (for example, mysqli ::__ construct ()) the log writing object determines whether the log writing directory exists and is written (the directory may not be created or changed), and the global configuration parsing object may need to locate the storage directory of the configuration file and perform file scanning.

These services consume considerable resources. If we need to do this once in a process, it will be very helpful for us to improve the running efficiency of the application.

3. Convenient global call

Because one of the major features of the Singleton mode is to obtain the object instance through the static method, it means that when accessing the object method, you do not need to first create an object instance. If you need to change the object, you need to use it in many places, this improves the convenience of calling.

Take a log operation class as an example:

The code is as follows: Copy code
Class Logger {

// First, you need a private static variable to store the generated object instance.
Private static $ instance;

// Business variable, saving the log writing path
Private $ logDir;

// Constructor. Note that the constructor must be private and cannot be instantiated externally (that is, new externally)
Private function _ construct (){
// Debug output, number of times the test object is new
Echo "new Logger instance rn ";
$ LogDir = sys_get_temp_dir (). DIRECTORY_SEPARATOR. "logs ";
If (! Is_dir ($ logDir) |! File_exists ($ logDir )){
@ Mkdir ($ logDir );
        }
$ This-> logDir = $ logDir;

    }

// Global access point of a unique instance. It is used to determine and return the object instance for external calls.
Public static function getInstance (){
If (is_null (self: $ instance )){
$ Class = _ CLASS __; // Obtain the object type. You can also use the new self () method.
Self: $ instance = new $ class ();
        }
Return self: $ instance;
    }

// Reload the _ clone () method. Object cloning is not allowed.
Public function _ clone (){
Throw new Exception ("Singleton Class Can Not Be Cloned ");
    }

// There are many methods for specific business methods.
Public function logError ($ message ){
$ LogFile = $ this-> logDir. DIRECTORY_SEPARATOR. "error. log ";
Error_log ($ message, 3, $ logFile );
    }
}

// Log call
$ Logger = Logger: getInstance ();
$ Logger-> logError ("An error occured ");
$ Logger-> logError ("Another error occured ");

// Or call
Logger: getInstance ()-> logError ("Still have error ");
Logger: getInstance ()-> logError ("I shocould fix it ");

In Singleton mode, you may encounter a special situation, such as database connection objects. For large applications, you may need to connect to multiple databases, therefore, an object shared by different databases may cause problems, such as connection allocation and retrieval.
Insert_id
,
Last_error
. This problem is also well solved by converting our $ instance variable into an associated array, pass different parameters to the getInstance method to get different "singleton objects" (the meaning of the quotation marks is: Strictly speaking, the class may be new multiple times, but this new is under our control, rather than outside the class ):

The code is as follows: Copy code
Class MysqlServer {
// Note: it turns into a plural number. ^_^ Of course, it's just for the identifier.
Private static $ instances = array ();

// Business variable to keep the mysqli object of the current instance
Private $ conn;

// Notable feature: private constructor to avoid instantiation outside the class
Private function _ construct ($ host, $ username, $ password, $ dbname, $ port ){
$ This-> conn = new mysqli ($ host, $ username, $ password, $ dbname, $ port );
    }

// Global access point of a unique instance
Public static function getInstance ($ host = 'localhost', $ username = 'root', $ password = '000000', $ dbname = 'mydb', $ port = '000000 ') {
$ Key = "{$ host }:{ $ port }:{ $ username }:{ $ dbname }";
If (empty (self: $ instances [$ key]) {
// The new self (); method can also be used here
$ Class = _ CLASS __;
Self: $ instances [$ key] = new $ class ($ host, $ username, $ password, $ dbname, $ port );
        }
Return self: $ instances [$ key];
    }

// Reload the _ clone method. Object instances cannot be cloned.
Public function _ clone (){
Throw new Exception ("Singleton Class Can Not Be Cloned ");
    }

// Query the business method. Other business methods are omitted later.
Public function query ($ SQL ){
Return $ this-> conn-> query ($ SQL );
    }

// Release resources as soon as possible
Public function _ destruct (){
$ This-> conn-> close ();
    }
}

Question 1: Can a singleton class have sub-classes? Because the constructor of Singleton classes is private, they cannot be inherited. To inherit, you need to change the constructor method to protected or public, this violates the intention of the Singleton mode. Therefore, if you want to add a subclass to a singleton class, you need to think about whether the pattern is incorrect or there is a problem with the structure design.

Question 2: The Singleton abuse mode is relatively easy to understand and implement. Therefore, once you realize the benefits of Singleton mode, you may want to write all classes into Singleton, therefore, before using the secondary mode, you must consider the above three cases to see if they are really necessary.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.