如何使用PHP5类创建单例类?
当前回答
PHP 5.3允许通过后期静态绑定创建可继承的单例类:
class Singleton
{
protected static $instance = null;
protected function __construct()
{
//Thou shalt not construct that which is unconstructable!
}
protected function __clone()
{
//Me not like clones! Me smash clones!
}
public static function getInstance()
{
if (!isset(static::$instance)) {
static::$instance = new static;
}
return static::$instance;
}
}
这解决了一个问题,在PHP 5.3之前,任何扩展了Singleton的类都会生成父类的实例,而不是它自己的实例。
现在你可以做:
class Foobar extends Singleton {};
$foo = Foobar::getInstance();
$foo将是Foobar的一个实例而不是Singleton的一个实例。
其他回答
以上答案都是可以的,但我还会再补充一些。
无论谁在2021年来到这里,我都将展示另一个使用单例模式类作为trait的例子,并在任何类中重用它。
<?php
namespace Akash;
trait Singleton
{
/**
* Singleton Instance
*
* @var Singleton
*/
private static $instance;
/**
* Private Constructor
*
* We can't use the constructor to create an instance of the class
*
* @return void
*/
private function __construct()
{
// Don't do anything, we don't want to be initialized
}
/**
* Get the singleton instance
*
* @return Singleton
*/
public static function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Private clone method to prevent cloning of the instance of the
* Singleton instance.
*
* @return void
*/
private function __clone()
{
// Don't do anything, we don't want to be cloned
}
/**
* Private unserialize method to prevent unserializing of the Singleton
* instance.
*
* @return void
*/
private function __wakeup()
{
// Don't do anything, we don't want to be unserialized
}
}
所以,像在任何课堂上一样轻松地使用它。假设,我们想在UserSeeder类中实现单例模式。
<?php
class UserSeeder
{
use Singleton;
/**
* Seed Users
*
* @return void
*/
public function seed()
{
echo 'Seeding...';
}
}
这应该是Singleton的正确方式。
class Singleton {
private static $instance;
private $count = 0;
protected function __construct(){
}
public static function singleton(){
if (!isset(self::$instance)) {
self::$instance = new Singleton;
}
return self::$instance;
}
public function increment()
{
return $this->count++;
}
protected function __clone(){
}
protected function __wakeup(){
}
}
所有这些复杂性(“后期静态绑定”……对我来说,harumph)只是PHP对象/类模型破碎的标志。如果类对象是一级对象(参见Python),那么"$_instance"将是一个类实例变量——类对象的成员,而不是其实例的成员/属性,也与它的后代共享相反。在Smalltalk世界中,这就是“类变量”和“类实例变量”之间的区别。
在PHP中,在我看来,我们似乎需要牢记模式是编写代码的指南——我们可能会考虑Singleton模板,但试图编写从实际的“Singleton”类继承的代码对PHP来说是错误的(尽管我认为一些有进取心的人可以创建一个合适的SVN关键字)。
我将继续使用共享模板分别编写每个单例。
请注意,我绝对不会参与单身是邪恶的讨论,生命太短暂了。
数据库类,检查是否有任何现有的数据库实例,它将返回先前的实例。
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
我同意第一个答案,但我也会将类声明为final,这样它就不能被扩展,因为扩展单例违背了单例模式。此外,实例变量应该是私有的,这样就不能直接访问它。还要将__clone方法设为私有,这样就不能克隆单例对象。
下面是一些示例代码。
/**
* Singleton class
*
*/
final class UserFactory
{
private static $_instance = null;
/**
* Private constructor
*
*/
private function __construct() {}
/**
* Private clone method
*
*/
private function __clone() {}
/**
* Call this method to get singleton
*
* @return UserFactory
*/
public static function getInstance()
{
if (self::$_instance === null) {
self::$_instance = new UserFactory();
}
return self::$_instance;
}
}
示例使用
$user_factory = UserFactory::getInstance();
这阻止你做什么(这将违反单例模式..
你不能这么做!
$user_factory = UserFactory::$_instance;
class SecondUserFactory extends UserFactory { }
推荐文章
- 工厂模式和策略模式之间的区别是什么?
- 在PHP单元测试执行期间,如何在CLI中输出?
- 在PHP中使用heredoc的优势是什么?
- PHP中的echo, print和print_r有什么区别?
- 如何向一个5岁的孩子解释依赖注入?
- 如何将XML转换成PHP数组?
- 如何将对象转换为数组?
- 从IP地址获取位置
- 在Java中使用“final”修饰符
- 获取数组值的键名
- HTTPS和SSL3_GET_SERVER_CERTIFICATE:证书验证失败,CA is OK
- PHP -获取bool值,当为false时返回false
- 在foreach中通过引用传递
- 如何触发命令行PHP脚本的XDebug分析器?
- 如何找出如果你使用HTTPS没有$_SERVER['HTTPS']