php设计模式总结-单件模式

一、单件模式

英文叫做sington。其他语言中有叫做单例模式,其实都是一样的道理。保证只会出现单个实例,所以是单例。翻译成单件,永远只会产生一件,呵呵。

还有翻译成单元素模式。其实关键是看这个英文比较好。英文是sington,统一是使用这个单词。

单件模式的目的我理解如下:

避免重复创建(实例化)对象,已经有现成的实例就用现成的。

减少资源的浪费(因为创建多个实例,浪费内存,完全没必要),单件模式保证了每时每刻引用的都是同一个实例。

为什么同时创建多个实例会引起逻辑上的错误呢?

$obj1
$obj2
多个实例。可能会覆盖掉里面的静态static变量吗? 不是这样子的。

其实是因为我目前还没遇到更加严重的问题。目前是简单的应用。

二、我觉得单件模式实践的注意点在下面几个方面

1、不要使用全局变量来保存实例值。因为全局变量在任何地方都可以被访问和修改,这就意味着可能会被其他代码给破坏掉值,这样就达不到永远是同一

个实例的效果。

2、使用static静态变量。这样只能函数内部访问。解决了全局变量被破坏的风险。

我觉得这是很多要做到实例唯一的一个关键部分。像框架中为保证所有对类实例的引用是唯一一个,都是将实例保存在static变量中。这样子下回调用的

时候也是同一个实例。不会重复创建。

抓住了这个精髓,我觉得是可以变化的。并不一定要遵循设计模式书中的做法。因为目标是相同的。技巧可以不同。

3、一般将类的__construct()构造函数标识为private,这样就是避免程序员直接实例化这个类。根据每种语言的特点,加上private关键词,程序员new一

个对象,就会报错。这种技巧是一种辅助手段。为保证只有一个类实例做辅助方案的。核心还是在于第二点的static关键字。

只要程序员约定好,这个辅助手段其实可以没有仍然能够做到单件。不是为设计模式而设计。了解实现目标才是关键的。

我在想,可以使用protected来替代吗?

目标就是,要禁止使用new来实例化这个函数。当实例化一个类的时候,默认会去执行构造函数,而加上protected和private关键字的成员,
都同样不能在类外部调用的。所以使用protected也是可行的。

但为什么要使用private呢?还有个好处,可以避免被继承的子类所重写,覆盖掉方法的内容。因为加上protected标识的成员是能够被子类给重写的。
既然对构造函数加上了private,那就意味着子类是不能继承这个类的。了解这个特性设计的时候就要考虑,无子类继承它的概念。

4、代码实践

class test
{

static $_instance = false;

private function __construct()
{

      /*一般将构造函数加上private关键字,这样子避免直接使用外部直接new来实例对象,当然内部使用new来创建是不会影响的*/
}

function get_instance()
{

          if(self::$_instance==false && !is_object(self::$_instance)){
       
         self::$_instance = new test();
      }
      return self::$_instance;

}

}

实际项目开发中,有个变体是,创建a、b、c的实例都需要通过一个公共的方法来调用,这样子可以实现单件模式。

类似于thinkphp等框架中的。

像下面是phpcms中的

pc_base::load_app_calss('test');

load_app_class($class_name)
{

static $class_array = array();

if(isset($class_array[$class_name]) && is_object($class_array[$class_name])) )
return $class_array[$class_name];
}else{
//这里可能还要有代码载入这个类文件,根据实际而定。可以是去默认一个文件夹夹中载入。也可以认为调用这个方法的前提是类文件要载入进来
$class_array[$class_name] = new $class_array[$class_name];
return $class_array[$class_name];

}

其实可以避免创建很多数据库链接。写到这里,我想起了mysql对于同一组参数进行的mysql_connect()连接,是不会重新建立连接的。php手册中对这个函

数的解释如下:

如果用同样的参数第二次调用 mysql_connect(),将不会建立新连接,而将返回已经打开的连接标识。

 

其实呢,只是mysql_connect这个函数做了可复用了。不讨论数据库连接方面。实例化其他的类,也需要创建大量的实例。占有资源。是指同一次执行的代

码过程中才能起到节省资源的效果

 

比如a.php的代码过程如下:

$class = test::get_instance();//得到这个test这个类的实例

$class->get_name();

get_count_number();//假设这个函数里面又需要用到那个类,则又需要进行实例化,如果统一调用get_instance()来获取实例,则前面得到的实例是可以

复用的。

 

三、单态模式(monostate)

1、单件模式还有一种变体:就是类的单件模式,也就是monostate模式。MonoState的意思就是"单一的状态"。也就是常说的单态。实现的目标为:所有实

例都是共享类中同一个值。

monostate的设计目标为:实现多个实例可以共享变量(类里面的属性),成为单态,尽管存在多个实例,但实例中的变量的最终只会有一个状态(可以理解为

一个值),不会出现多个值(也就是每个实例里面的变量都是不同的值)。

2、它与单件的区别为:

单件是将构造函数声明为private,来保证只有一个实例。而单态则不需要。它关注的侧重点是最终只有一个数值,而用户实例化多少类,不是它所关心的


MonoState并不限制创建对象的个数,但是它的状态却只有一个状态。

3、monostate模式实践

实践要点:把类里面的变量(属性)标识为static即可

<?php

class test
{

static $_state = array();

function set($key,$value)
{
  self::$_state[$key]= $value;
}

function get($key)
{

   return self::$_state[$key];

}

}

$obj = new test();

$obj->set('name','wangtao');

$obj->set('sex','male');

echo $obj->get('name');//得到结果是wangtao

//再次实例化一次,看访问对象的成员,是否得到一样的数据。
$obj2 = new test();

echo $obj2->get('name');//输出wangtao

 

//再次新创建一个实例$obj2,访问name这个变量,数据是共享的,所以输出还是wangtao。当然使用set()把值改变了,其他实例也会访问到改变后的值。

总结:实现monostate模式,具体实现有多种办法,只要达到共享数据的目的就ok。比如使用$_GLOABS[]全局变量,把数据保存在全局变量中,然后放到类

成员中也可以,《php设计模式》这本书就是使用这种形式实现。使用静态变量(static关键字)也可以。上面使用的就是静态变量的方式。我觉得使用

static方式更加直观易懂

四、思考:sington与monostate能混合一起实现吗?

既然sington模式可以避免创建多个实例。而monostate是关注多个实例之间共享数据。

那么有没有种办法让两者混合呢。

也就是说:我构造一个类,既能够达到单件的效果,也能实现monostate的效果。开玩笑玩玩,呵呵,加深深入理解。

我觉得,单件关注的是实例化一个类。monostate关注的状态的一致性。其实两者是不相容的。

如果实现了单件模式。那么就不存在多个实例对象存在。既然都是调用同一个实例,这样子里面的成员变量肯定是共享的,因为使用的是同一个实例的成员

。为此我特意做试验,如下:

class test
{

static $_state;//实现单态,就是将里面变量定义为static即可,现在这个类实现了monostate模式
static $_instance = false;

private function __construct()
{

}

/*
实现单例模式
*/
function get_instance()
{

       if(self::$_instance==false && !is_object(self::$_instance)){
       
         self::$_instance = new test();
      }
      return self::$_instance;

}

}

$obj1 = test::get_instance();
$obj1->_state = 20;

$obj2 = test::get_instance();//因为这里引用的还是同一个实例,所以下面输出属性的值,还是前面更改的20

echo $obj2->_state;

 

 

以上是给自己总结用。不正确之处欢迎指正。

时间: 2024-09-01 21:20:57

php设计模式总结-单件模式的相关文章

.NET设计模式:单件模式(Singleton Pattern)

概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点.这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任. 从另一个角度来说,Singleton模式其实也是一种职责型模式.因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责! 意图

艾伟_转载:.NET设计模式:单件模式(Singleton Pattern)

概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问点.这就提出了一个问题:如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?客户程序在调用某一个类时,它是不会考虑这个类是否只能有一个实例等问题的,所以,这应该是类设计者的责任,而不是类使用者的责任. 从另一个角度来说,Singleton模式其实也是一种职责型模式.因为我们创建了一个对象,这个对象扮演了独一无二的角色,在这个单独的对象实例中,它集中了它所属类的所有权力,同时它也肩负了行使这种权力的职责! 意图

.NET简谈设计模式之(单件模式)

我们继续学习设计模式系列文章. 今天要讲的是单件模式,其实单件模式是比较简单的设计模式,在我们日常开发过程中也是经常用到的. 单件模式:单件模式是一种用于确保整个应用程序中只有一个类实例且这个实例所占资源在整个应用程序中是共享时的程序设计方法. 我想如果初学者对一些基本概念能熟练掌握时,其实单件模式是很简单的,就是因为初学者对一些概念还不是很理解,我们先来扫除这些阻挡我们理解的障碍. 大部分的初学者都会搞不清楚"静态对象"与"实例对象"的区别.当然谁都有一个过渡期,

设计模式之单件模式(Singleton Pattern )

设计 单件模式 Singleton Pattern Singleton 模式,它包含在创造性模式系列中. 创造性模式指示如何以及何时创建对象.Singleton 模式可以保证一个类有且只有一个实例,并提供一个访问它的全局访问点.在程序设计过程中,有很多情况需要确保一个类只能有一个实例.例如,系统中只能有一个窗口管理器.一个打印假脱机,或者一个数据引擎的访问点.PC机中可能有几个串口,但只能有一个COM1实例. 其结构如下: 我们可以定义一个Spooler类,实现Singleton 模式 Publ

PHP设计模式介绍Ⅳ单件模式

  几乎所有面向对象的程序中,总有一两个资源被创建出来,在程序应用中持续被共享使用.例如,这样的一个资源,在一个电子商务程序的数据库连接中使用:这个连接在应用程序启动时初始化,程序于是可以有效的执行;当程序结束时,这个连接最终被断开并销毁.如果是你写的代码,没必要在每时每刻创建一个数据库连接,这样非常低效.已经建立好的连接应该能被你的代码简单重复的使用.这个问题就是,基于以上要求你将如何进行这个数据库连接?(或者连接其它被循环使用的唯一资源,比如一个开放文件或者一个队列.) 问题 你怎样确保一个

JavaScript设计模式之单件模式介绍_javascript技巧

单件模式说明 1. 说明:单件模式,就是静态化的访问中已经实例化的对象,这个对象只能通过一个唯一的入口访问,已经实例或待实例化的对象:面向对象语言如Java, .Net C#这样的服务端动态语言里,能保证类的操作有顺的进行,避免并行操作使数据发生混乱的情况: 2. 单件模式的好处: 1>. 减少 new 的操作,以免加快内存频繁操作,占用内存: 2>. 尽量减少大系统的对象的开销: 3>. 就是上面说的,可以保障某些类型的操作有顺序准确的操作,以免并行处理引起的数据异常现象: 当然上面说

温故而知新:设计模式之单件模式(Singleton)

 1 using System; 2  3 namespace Singleton 4 { 5     class Program 6     { 7         static void Main(string[] args) 8         { 9             Singleton s1 = Singleton.Instance;10             Singleton s2 = Singleton.Instance;11 12             Console

设计模式应用实例之单件模式应用,和简单注入实现形式

上次写了基于MVC模式和Command模式构建系统架构,也做了一个简单的实例. 在把我想写的写完以后,我想通过一个具体的项目来串联大部分的设计模式思想. 今天我想说的是单件模式. 首先简单介绍下单件模式是什么东西,也称Singleton模式,实现单一实例的功能,不具体说了,不了解者看别的介绍概念性文章. 通常,在我做过的项目中,应用Singleton最多的就是做适配器,下面我会介绍如何做适配器. 先介绍通过通过单件模式,实现适配器产生单一实例的应用过程. 在介绍单件模式以前,我想先介绍下,面向服

设计模式(二)单件模式Singleton(创建型)

SINGLETON(单件)-对象创建型模式        几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的.您希望在应用程序中共享数据库句柄,因为在保持连接打开或关闭时,它是一种开销.再如大家最经常用的IM,如QQ,在同一台电脑,一个帐号只能有唯一的登录. 1. 问题 怎样确保一个特殊类的实例是独一无二的(它是这个类的唯一实例),并且这个实例易于被访问呢? 2. 解决方案 1)全局变量:一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个