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;
以上是给自己总结用。不正确之处欢迎指正。
php设计模式总结-单件模式的更多相关文章
- 设计模式之单件模式(Singleton Pattern)
一.单件模式是什么? 单件模式也被称为单例模式,它的作用说白了就是为了确保“该类的实例只有一个” 单件模式经常被用来管理资源敏感的对象,比如:数据库连接对象.注册表对象.线程池对象等等,这种对象如果同 ...
- 设计模式入门,单件模式,c++代码实现
// test05.cpp : Defines the entry point for the console application.// #include "stdafx.h" ...
- 【设计模式】单件模式(Singleton)--各类单件模式的比较
单件模式 确保一个类只有一个实例,并提供一个安全的访问点. 线程安全+延时初始化+高性能(使用:延时初始化占位符模式) ------测试----------- 线程安全+[非]延时初始化 线程安全+延 ...
- C#设计模式:单件(例)模式 -- 类也玩计划生育
这里写的代码,相当于<Head First 设计模式>的读书笔记,原书是java的,自己在学习的过程中将其翻译为C#: (一)剖析经典的单件模式实现 单件模式 -- 确保一个类只有一个实例 ...
- C#设计模式——单件模式
一.为何需要单件模式 需求 我们开发了一个大型的项目,其中存在许多的工具类.但是其中很多的工具类我们并不是经常使用得到,甚至 一次都不会使用.但是这些工具类都是静态的类,会消耗很多的内存,即使一次都不 ...
- .NET设计模式(2):单件模式(Singleton Pattern)
转载:http://terrylee.cnblogs.com/archive/2005/12/09/293509.html 单件模式(Singleton Pattern) --.NET设计模式系列之二 ...
- NET设计模式(2):单件模式(Singleton Pattern)[转载]
单件模式(Singleton Pattern) ——.NET设计模式系列之二 Terrylee,2005年12月07日 概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问 ...
- 设计模式(二)单件模式Singleton(创建型)
SINGLETON(单件)—对象创建型模式 几乎所有面向对象的程序中,总有一些类的对象需要是唯一的,例如,通过数据库句柄到数据库的连接是独占的.您希望在应用程序中共享数据库句柄,因为在保持连接打开或关 ...
- .NET设计模式 第二部分 创建型模式(1)—:单件模式(Singleton Pattern)
单件模式(Singleton Pattern) ——.NET设计模式系列之二 Terrylee,2005年12月07日 概述 Singleton模式要求一个类有且仅有一个实例,并且提供了一个全局的访问 ...
随机推荐
- golang学习笔记 ---数组与切片
数组: golang数组包含的每个数据称为数组元素(element),数组包含的元素个数被称为数组长度(length). golang数组的长度在定义后不可更改,并且在声明时可以是一个常量或常量表达式 ...
- SimpleAdapter真不简单!
作为一名编程初学者,我总是认为自己什么都不会,什么都不行,就算实现了文档指定的功能,我永远都是觉得自己写过的代码实在是太烂了,它只是恰巧能够运行而已!它只是在运行的时候恰巧没有发现错误而已!!一直都是 ...
- STL 的string类怎么啦?
前言 上个周末在和我的同学爬香山闲聊时,同学说到STL中的string类曾经让他备受折磨,几年前他开发一个系统前对string类还比较清楚,然后随着程序的复杂度的加深,到了后期,他几乎对strin ...
- excel中对数据进行分类求和
我们在用excel处理数据时,常常需要按不同的类别分别汇总数据.例如下图中需要求出每个业务员的总销售金额等. 通常情况下我们的数据量很大,而且需要较快的统计出来结果,所以我们要用一定的技巧才能计算出来 ...
- Win8.1开机自启动程序
动机: 开机自启动goagent与锐捷 问题: goagent没有自启动选项;锐捷开启"登录后启动"却一直没有启动 解决方案: 使用计划任务启动goagent+彻底关闭UAC使锐捷 ...
- hive splict, explode, lateral view, concat_ws
hive> create table arrays (x array<string>) > row format delimited fields terminated by ...
- eclipse下SVN subclipse插件
本文目的 让未使用过版本控制器软件或者未使用过subversion软件的人员尽快上手. subversion的使用技巧很多,这里只总结了最小使用集,即主要的基本功能,能够用来应付日常工作. 因此不涉及 ...
- mysql定时执行某任务
查看event是否开启: show variables like '%sche%'; 将事件计划开启: set global event_scheduler=1; 关闭事件任务: alter even ...
- Atitit opencv模板匹配attilax总结
Atitit opencv模板匹配attilax总结 找一幅图像的匹配的模板,可以在一段视频里寻找出我们感兴趣的东西,比如条形码的识别就可能需要这样类似的一个工作提取出条形码区域(当然这样的方法并不鲁 ...
- Xilinx FPGA用户约束文件(转自xilinx ISE 开发指南
FPGA设计中的约束文件有3类:用户设计文件(.UCF文件).网表约束文件(.NCF文件)以及物理约束文件(.PCF文件),可以完成时序约束.管 脚约束以及区域约束.3类约束文件的关系为:用户在设计输 ...