如何使用PHP5类创建单例类?
当前回答
我很久以前就写过,想在这里分享
class SingletonDesignPattern {
//just for demo there will be only one instance
private static $instanceCount =0;
//create the private instance variable
private static $myInstance=null;
//make constructor private so no one create object using new Keyword
private function __construct(){}
//no one clone the object
private function __clone(){}
//avoid serialazation
public function __wakeup(){}
//ony one way to create object
public static function getInstance(){
if(self::$myInstance==null){
self::$myInstance=new SingletonDesignPattern();
self::$instanceCount++;
}
return self::$myInstance;
}
public static function getInstanceCount(){
return self::$instanceCount;
}
}
//now lets play with singleton design pattern
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
$instance = SingletonDesignPattern::getInstance();
echo "number of instances: ".SingletonDesignPattern::getInstanceCount();
其他回答
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();
这应该是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(){
}
}
我知道这可能会引起不必要的争论,但是我知道您可能需要多个数据库连接,所以我承认单例可能不是最好的解决方案……然而,我发现单例模式还有其他非常有用的用途。
Here's an example: I decided to roll my own MVC and templating engine because I wanted something really lightweight. However, the data that I want to display contains a lot of special math characters such as ≥ and μ and what have you... The data is stored as the actual UTF-8 character in my database rather than pre-HTML-encoded because my app can deliver other formats such as PDF and CSV in addition to HTML. The appropriate place to format for HTML is inside the template ("view" if you will) that is responsible for rendering that page section (snippet). I want to convert them to their appropriate HTML entities, but PHPs get_html_translation_table() function is not super fast. It makes better sense to retrieve the data one time and store as an array, making it available for all to use. Here's a sample I knocked together to test the speed. Presumably, this would work regardless of whether the other methods you use (after getting the instance) were static or not.
class EncodeHTMLEntities {
private static $instance = null;//stores the instance of self
private $r = null;//array of chars elligalbe for replacement
private function __clone(){
}//disable cloning, no reason to clone
private function __construct()
{
$allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
$specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
$this->r = array_diff($allEntities, $specialEntities);
}
public static function replace($string)
{
if(!(self::$instance instanceof self) ){
self::$instance = new self();
}
return strtr($string, self::$instance->r);
}
}
//test one million encodings of a string
$start = microtime(true);
for($x=0; $x<1000000; $x++){
$dump = EncodeHTMLEntities::replace("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)");
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds using singleton\n";
//now repeat the same without using singleton
$start = microtime(true);
for($x=0; $x<1000000; $x++){
$allEntities = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
$specialEntities = get_html_translation_table(HTML_SPECIALCHARS, ENT_NOQUOTES);
$r = array_diff($allEntities, $specialEntities);
$dump = strtr("Reference method for diagnosis of CDAD, but clinical usefulness limited due to extended turnaround time (≥96 hrs)", $r);
}
$end = microtime(true);
echo "Run time: ".($end-$start)." seconds without using singleton";
基本上,我看到的典型结果如下:
php test.php Run time: 27.842966794968 seconds using singleton Run time: 237.78191494942 seconds without using singleton
因此,虽然我不是专家,但我认为没有更方便、更可靠的方法来减少对某些数据的缓慢调用的开销,同时使其超级简单(只需一行代码就可以完成所需的工作)。假设我的例子只有一个有用的方法,因此并不比一个全局定义的函数好,但是一旦你有了两个方法,你就想把它们组合在一起,对吗?我是不是太离谱了?
此外,我更喜欢真正做一些事情的例子,因为有时很难想象一个例子中包含“//在这里做一些有用的事情”这样的语句,这是我在搜索教程时经常看到的。
无论如何,我希望有任何关于为什么在这种情况下使用单例是有害的(或过于复杂)的反馈或评论。
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的一个实例。
你可能应该添加一个私有的__clone()方法来禁止克隆实例。
private function __clone() {}
如果您不包含此方法,则可能出现以下情况
$inst1=UserFactory::Instance(); // to stick with the example provided above
$inst2=clone $inst1;
现在$inst1 !== $inst2 -它们不再是同一个实例了。
推荐文章
- 在PHP5中创建单例设计模式
- 什么时候我们应该使用观察者和可观察对象?
- 阻止人们入侵基于php的Flash游戏高分表的最佳方法是什么
- PHP子字符串提取。获取第一个'/'之前的字符串或整个字符串
- __construct函数的作用是什么?
- PHP中的异步shell执行器
- Laravel 5 -如何访问在视图存储上传的图像?
- 为什么在PHP中使用sprintf函数?
- “质量分配”在Laravel中是什么意思?
- 在逗号上爆炸字符串,并修剪每个值的潜在空格
- PHP与MySQL 8.0+错误:服务器请求身份验证方法未知的客户端
- laravel5“LIKE”对等物(雄辩的)
- 在函数中使用默认实参
- 转换php数组到Javascript
- PHP PDO:字符集,集名称?