Introduction to PHP design mode Ⅳ single piece mode

Source: Internet
Author: User
Tags constructor mathematical constants php error valid

In almost all object-oriented programs, there are one or two of resources that are created to be shared and used consistently in program applications. For example, such a resource is used in a database connection of an e-business program: The connection is initialized at the time the application is started, and the program is executed efficiently, and when the program ends, the connection is eventually disconnected and destroyed. If you write the code, there is no need to create a database connection every moment, which is very inefficient. Already established connections should be used simply and repeatedly by your code. The question is, how will you make this database connection based on the above requirements? (or to connect to other unique resources that are recycled, such as an open file or a queue.) )

Problem

How do you make sure that an instance of a particular class is unique (it is the only instance of the class) and that it is easy to access?

Solution

Of course, global variables are the obvious solution. But it's like Pandora's Box (the right judgment comes from experience, and wrong judgments produce experience.) That's what the proverb means. , any of your code can modify global variables, which will inevitably cause more debugging surprises. In other words, there are always problems with the state of a global variable (here's a good description of the global variable usage problem, Http://c2.com/cgi/wiki?GlobalVariablesAreBad).

When you need a unique instance of a particular class, use this name as a single piece of mode. A class based on a single piece pattern can instantiate and initialize an instance of this class, and provide an absolutely identical connection every moment. Typically, a static method named GetInstance () is implemented.

The key question is how to get a precise and unified example at every moment. Take a look at the following example:

PHP4

function Testgetinstance () {

$this->assertisa (

$obj 1 =& dbconn::getinstance (),

' Dbconn ',

' The returned object is a instance of Dbconn ');

$this->assertreference (

$obj 1,

$obj 2 =& dbconn::getinstance (),

' Two calls to getinstance () return the same object ');

}

Note: assertreference

The Assertreference () method ensures that two parameters that are passed are referenced from the same PHP variable.

In PHP4, it is asserted that two of the parameters tested are the same object. Assertreference () This method may be deprecated after porting to PHP5.

This test method has two assertions: the first to determine that the value returned by the call to the static method Dbconn::getinstance () is an instance of the Dbconn object, and the second is used to determine that the second call to the getinstance () method returns a value that references the same object instance. This means that they are using the same object.

In addition to asserting the expected execution of the code, test also predicts the correct use of getinstance (PHP4): $local _conn_var=&dbconn::getinstance (). The return value of a reference (=&) static method is assigned to this local variable.

Write another section of the test code: instantiating a single piece class directly with "new" can cause some type of error. The test code is as follows:

function Testbadinstantiate () {

$obj =& New Dbconn;

$this->asserterrorpattern (

'/(Bad|nasty|evil|do Not|don ' T|warn). * '.

' (instance|create|new|direct)/I ');

}

This code directly creates a Dbconn instance that will cause a PHP error. To make the code more stable, we use pcre regular expressions to match the error message. (The exact wording that displays the error message is not important.) )

[Next]

Sample code

Single-piece mode is a very interesting pattern. Let's explore its implementation with PHP4 and PHP5 two ways, now starting with PHP4.

Global Approach

In theory, a global variable can produce a perfect single piece, but a global variable can be modified: it is not guaranteed that the global variable points to an object while the code is running. Therefore, you can reduce the problem of "too random Access" global variables by not having global variables directly referenced globally. For example, this code uses a very long and unique name to "hide" the reference to a global variable.

Class Dbconn {

function Dbconn ($fromGetInstance =false) {

if (m_e!= $fromGetInstance) {

Trigger_error (' The Dbconn class is a Singleton, '

. ' Please does not instantiate directly ');

}

}

function &getinstance () {

$key = ' __some_unique_key_for_the_dbconn_instance__ ';

if (!) ( Array_key_exists ($key, $GLOBALS) && is_object ($GLOBALS [$key])

&& ' dbconn ' = Get_class ($GLOBALS [$key])) {

$GLOBALS [$key] =& new Dbconn (m_e);

}

return $GLOBALS [$key];

}

}

In the Dbconn constructor, you may be puzzled by the default parameters of the $fromgetinstance. When an object is directly instantiated, it can provide (very faint) protection: Unless the default value becomes E (m_e = 2.718281828459 in the mathematical constants of PHP), this code will complain.

represented as a UML class diagram, the solution is as follows:

If you do not use this "mystery parameter"-type protection, creating a global tag is another option, using it to verify that you are creating an object through the getinstance () method. The protection mode changes from "You know its name" to "it exists in the environment".

Here's an example that explains why the constructor protection code has a global identity:

Class Dbconn {

function Dbconn () {

$token = ' __some_dbconn_instance_create_semaphore__ ';

if (!array_key_exists ($token, $GLOBALS)) {

Trigger_error (' The Dbconn class is a Singleton, '

. ' Please does not instantiate directly ');

}

}

function &getinstance () {

Static $instance = Array ();

if (! $instance) {

$token = ' __some_dbconn_instance_create_semaphore__ ';

$GLOBALS [$token] = true;

$instance [0] =& new Dbconn;

Unset ($GLOBALS [$token]);

}

Tips

PHP4 allows you to change the value of $this in the constructor. In the past, we'll get used to setting $this = null; when there is a create construct error, make sure that the invalid object cannot be used by the code. Something useful in PHP4 is not compatible in PHP5 and will be validated in your code in the future, and this technique is no longer recommended.

Another focus in this code is the use of reference operations &. There are two kinds of places to use &. The first is when the function is defined, the function name is used to indicate that a reference will be returned. The second is to assign the new Dbconn object to the $globals array. (Mentioned in the preamble and value object chapters: In PHP4, you always use the & operator to create, pass, and return objects in a reference way)

The conditional check of the getinstance () method is often written without warning and is not even prompted at the E_all error level. It checks whether there is a Dbconn object in the appropriate position in the $global array, and if not, creates the object there. This method then returns the result that the object can be repeatedly created or that the object was previously created by this method. When the method is finished, you can confirm that you already have a valid instance of the class, and that it has been initialized effectively.

[Next]

static mode

Problems with global variables even exist in global variables that are hidden in getinstance (). Because global variables are valid anywhere in the script, you may still be able to break the global variable without noticing,

Using static variables inside the getinstance () method to store Singleton is a neat way to look. The first code fragment is as follows:

Class Dbconn {

// ...

function &getinstance () {

static $instance = false;

if (! $instance) $instance =& new Dbconn (m_e);

return $instance;

}

}

The Zend 1 engine cannot store references to static variables in PHP4 (see http://www.php.net/manual/en/language.variables.scope.php#AEN3609). Stores a static array using a workspace and places a reference to the singleton instance in a known array. The getinstance () method is as follows:

Class Dbconn {

function Dbconn ($fromGetInstance =false) {

if (m_e!= $fromGetInstance) {

Trigger_error (' The Dbconn class is a Singleton, '

. ' Please does not instantiate directly ');

}

}

function &getinstance () {

Static $instance = Array ();

if (! $instance) $instance 0 =& New Dbconn (m_e);

return $instance 0;

}

}

This code simply chooses the first element of this static array $instancede to hold the reference to the Dbconns instance of a single piece.

Although this code is somewhat dependent on the boolean approach of PHP, it is more rigorous than the global version: When a condition is detected, using an empty array can result in false results. As in the previous version of the Dbconn class, you need to refer to the operator in the definition and Assignment section of the function.

Single-piece mode in PHP5

PHP5 is easier to implement in a single piece mode, PHP5 access control for internal variables and functions of the class is enhanced. The Dbconn::_construct () construction method is set to private (private), and the class cannot be instantiated directly. In the UML diagram, the PHP5 dbconn single piece mode is as follows:

The combination uses static methods and static variables to persist this instance, and set the constructor to private to prevent a direct instantiation of the class and create an instance with the following code:

Class Dbconn {

/**

* Static property to hold Singleton instance

*/

static $instance = false;

/**

* Constructor

* Private So-getinstance () method can instantiate

* @return void

*/

Private Function __construct () {}

/**

* Factory the Singleton instance

* @return Dbconn

*/

Public Function getinstance () {

if (! Dbconn:: $instance) {

Dbconn:: $instance = new Dbconn;

}

Return Dbconn:: $instance;

}

}

Note : Please pay attention to the triple programming Tutorials section for more wonderful articles .

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.