单例模式属于创建型模式,它是设计模式中最简单的一种模式,当然它的使用也是无处不在的。
单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。
当需要控制一个类的实例数量,且调用者可以从一个公共的众所周知的访问点访问时,我们就可以考虑使用单例模式了。
我们用 UML 来设计单例模式,当然在以后的设计模式的设计部分,我们都将采用 UML 来描述我们的设计,这样就更为形象化了。
从 UML 设计图中我们可以看出,为了让一个类只有一个实例,它必须创建一个静态变量,然后我们用一个公共静态的 Instance() 的方法来创建它,但是为了避免这个类自身的构造函数可以创建对象,我们将构造函数设置成 protected 或者 private,这样外部就只能通过 Instance() 的方法来创建一个静态的 Singleton 类。看来这样我们达到了我们的目的,接下来我们看代码:
public class Singleton {
private static Singleton instance;
protected Singleton()
public static Singleton Instance() {
if(instance != null) instance = new Singleton();
return instance;
}
}
由此看来,实现单例模式我们可以做下列几步:
在类中创建一个静态变量,变量类型为当前类;
在类中创建一个公共的静态方法,让用户可以通过此方法创建此类的静态对象;
最后将构造函数设置为 protected 或者 private。
Program List:最简单的单例类
class Fruit
{
static private $_color;
private function __construct()
{
}
static public function singleton() {
return isset(self::$_color) ? self::$_color : self::$_color = new self();
}
}
?>
Program List:可扩展的单例类
一个可扩展的单例类看似不可能,但下面的程序很接近这种效果。
class Test extends Fruit {
public static function getInstance()
{
return Fruit::getSingleton(get_class());
}
}
?>
class Fruit {
/***********************
* HOW TO USE
*
* Inherit(extend) from Singleton and add getter:
*
* //public getter for singleton instance
* public static function getInstance(){
* return Singleton::getSingleton(get_class());
* }
*
*/
private static $instanceMap = array();
//protected getter for singleton instances
protected static function getSingleton($className)
{
if(!isset(self::$instanceMap[$className]))
{
$object = new $className;
//Make sure this object inherit from Singleton
if($object instanceof Fruit)
{
self::$instanceMap[$className] = $object;
}
else
{
throw SingletonException("Class '$className' do not inherit from Singleton!");
}
}
return self::$instanceMap[$className];
}
//protected constructor to prevent outside instantiation
protected function __construct(){
}
//denie cloning of singleton objects
public final function __clone(){
trigger_error('It is impossible to clone singleton', E_USER_ERROR);
}
}
?>
class Apple extends Fruit {
protected $rndId;
protected function __construct(){
$this->rndId = rand();
}
public function whatAmI(){
echo 'I am a Apple('.$this->rndId.')
';
}
public static function getInstance(){
return Fruit::getSingleton(get_class());
}
}
class GreenApple extends Apple {
public function whatAmI(){
echo 'I am a GreenApple('.$this->rndId.')
';
}
public static function getInstance(){
return Fruit::getSingleton(get_class());
}
}
$apple1 = Apple::getInstance();
$apple2 = GreenApple::getInstance();
$apple1->whatAmI();// should echo 'I am a A(some number)
$apple2->whatAmI();// should echo 'I am a B(some number)
$apple1 = Apple::getInstance();
$apple2 = GreenApple::getInstance();
$apple1->whatAmI();// should echo 'I am a A(same number as above)
$apple2->whatAmI();// should echo 'I am a B(same number as above)
// $a = new A();// this should fail
// $b = new B();// this should fail
?>
程序运行结果:
I am a Apple(4462)
I am a GreenApple(8207)
I am a Apple(4462)
I am a GreenApple(8207)
Program List:单例类与其派生类
class Fruit
{
// Hold an instance of the class
private static $instance;
// A private constructor; prevents direct creation of object
protected function __construct()
{
echo 'I am constructed';
}
// The singleton method
public static function singleton($classname = __CLASS__)
{
if (!isset(self::$instance)) {
self::$instance = new $classname;
}
return self::$instance;
}
}
class Apple extends Fruit {
public static function singleton()
{
return parent::singleton(__CLASS__); // NOTE The singleton method MUST return an instance.
}
public function showColor()
{
echo 'My Color is Red.';
}
}
$subclassInstance = Apple::singleton();
$subclassInstance->showColor();
?>
程序运行结果:
I am constructed
My Color is Red.