如何使用PHP5类创建单例类?
当前回答
支持多对象,每类一行:
这个方法将在你想要的任何类上强制单例,你所要做的就是向你想要创建单例的类中添加一个方法,这个方法会为你做这件事。
这也将对象存储在“SingleTonBase”类中,因此您可以通过递归SingleTonBase对象来调试您在系统中使用的所有对象。
创建一个名为SingletonBase.php的文件,并将其包含在脚本的根目录中!
代码是
abstract class SingletonBase
{
private static $storage = array();
public static function Singleton($class)
{
if(in_array($class,self::$storage))
{
return self::$storage[$class];
}
return self::$storage[$class] = new $class();
}
public static function storage()
{
return self::$storage;
}
}
然后,对于任何你想要创建单例的类,只需添加这个小的单方法。
public static function Singleton()
{
return SingletonBase::Singleton(get_class());
}
这里有一个小例子:
include 'libraries/SingletonBase.resource.php';
class Database
{
//Add that singleton function.
public static function Singleton()
{
return SingletonBase::Singleton(get_class());
}
public function run()
{
echo 'running...';
}
}
$Database = Database::Singleton();
$Database->run();
你可以在任何类中添加这个单例函数,每个类只创建一个实例。
注意:你应该始终将__construct设为private以消除new Class()的使用;实例化。
其他回答
这是在数据库类上创建单例的例子
设计模式 1)单
class Database{
public static $instance;
public static function getInstance(){
if(!isset(Database::$instance)){
Database::$instance=new Database();
return Database::$instance;
}
}
$db=Database::getInstance();
$db2=Database::getInstance();
$db3=Database::getInstance();
var_dump($db);
var_dump($db2);
var_dump($db3);
那么输出是
object(Database)[1]
object(Database)[1]
object(Database)[1]
只使用单个实例,不要创建3个实例
<?php
/**
* Singleton patter in php
**/
trait SingletonTrait {
protected static $inst = null;
/**
* call this method to get instance
**/
public static function getInstance(){
if (static::$inst === null){
static::$inst = new static();
}
return static::$inst;
}
/**
* protected to prevent clonning
**/
protected function __clone(){
}
/**
* protected so no one else can instance it
**/
protected function __construct(){
}
}
使用方法:
/**
* example of class definitions using SingletonTrait
*/
class DBFactory {
/**
* we are adding the trait here
**/
use SingletonTrait;
/**
* This class will have a single db connection as an example
**/
protected $db;
/**
* as an example we will create a PDO connection
**/
protected function __construct(){
$this->db =
new PDO('mysql:dbname=foodb;port=3305;host=127.0.0.1','foouser','foopass');
}
}
class DBFactoryChild extends DBFactory {
/**
* we repeating the inst so that it will differentiate it
* from UserFactory singleton
**/
protected static $inst = null;
}
/**
* example of instanciating the classes
*/
$uf0 = DBFactoryChild::getInstance();
var_dump($uf0);
$uf1 = DBFactory::getInstance();
var_dump($uf1);
echo $uf0 === $uf1;
respose:
object(DBFactoryChild)#1 (0) {
}
object(DBFactory)#2 (0) {
}
如果你使用的是PHP 5.4: trait,它是一个选项,所以你不必为了拥有单例模式而浪费继承层次结构
还要注意你是使用trait还是扩展Singleton类 如果你不添加以下代码行,就会创建子类的单例:
protected static $inst = null;
在儿童班
意想不到的结果将是:
object(DBFactoryChild)#1 (0) {
}
object(DBFactoryChild)#1 (0) {
}
数据库类,检查是否有任何现有的数据库实例,它将返回先前的实例。
class Database {
public static $instance;
public static function getInstance(){
if(!isset(Database::$instance) ) {
Database::$instance = new Database();
}
return Database::$instance;
}
private function __cunstruct() {
/* private and cant create multiple objects */
}
public function getQuery(){
return "Test Query Data";
}
}
$dbObj = Database::getInstance();
$dbObj2 = Database::getInstance();
var_dump($dbObj);
var_dump($dbObj2);
/*
After execution you will get following output:
object(Database)[1]
object(Database)[1]
*/
Ref http://www.phptechi.com/php-singleton-design-patterns-example.html
制作单例模式的真实和现代方法是:
<?php
/**
* Singleton Pattern.
*
* Modern implementation.
*/
class Singleton
{
/**
* Call this method to get singleton
*/
public static function instance()
{
static $instance = false;
if( $instance === false )
{
// Late static binding (PHP 5.3+)
$instance = new static();
}
return $instance;
}
/**
* Make constructor private, so nobody can call "new Class".
*/
private function __construct() {}
/**
* Make clone magic method private, so nobody can clone instance.
*/
private function __clone() {}
/**
* Make sleep magic method private, so nobody can serialize instance.
*/
private function __sleep() {}
/**
* Make wakeup magic method private, so nobody can unserialize instance.
*/
private function __wakeup() {}
}
现在你可以用它。
<?php
/**
* Database.
*
* Inherited from Singleton, so it's now got singleton behavior.
*/
class Database extends Singleton {
protected $label;
/**
* Example of that singleton is working correctly.
*/
public function setLabel($label)
{
$this->label = $label;
}
public function getLabel()
{
return $this->label;
}
}
// create first instance
$database = Database::instance();
$database->setLabel('Abraham');
echo $database->getLabel() . PHP_EOL;
// now try to create other instance as well
$other_db = Database::instance();
echo $other_db->getLabel() . PHP_EOL; // Abraham
$other_db->setLabel('Priler');
echo $database->getLabel() . PHP_EOL; // Priler
echo $other_db->getLabel() . PHP_EOL; // Priler
正如你所看到的,这种实现更加灵活。
class Database{
//variable to hold db connection
private $db;
//note we used static variable,beacuse an instance cannot be used to refer this
public static $instance;
//note constructor is private so that classcannot be instantiated
private function __construct(){
//code connect to database
}
//to prevent loop hole in PHP so that the class cannot be cloned
private function __clone() {}
//used static function so that, this can be called from other classes
public static function getInstance(){
if( !(self::$instance instanceof self) ){
self::$instance = new self();
}
return self::$instance;
}
public function query($sql){
//code to run the query
}
}
Access the method getInstance using
$db = Singleton::getInstance();
$db->query();