首页 > PHP > 设计模式之PHP项目应用——单例模式设计Memcache和Redis操作类
2015
07-24

设计模式之PHP项目应用——单例模式设计Memcache和Redis操作类

1 单例模式简介

单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

2 模式核心思想

1)某个类只能有一个实例;
2)它必须自行创建这个实例;

3)它必须自行向整个系统提供这个实例。

3 模式架构图

设计模式之PHP项目应用——单例模式设计Memcache和Redis操作类 - 第1张  | 大话运维

4 项目应用

4.1 需求说明

CleverCode在实际的PHP项目中,应用单例模式最多的就是涉及到网络连接的。比如Memcache和Redis连接,一般的需求通常Redis都只有一台服务器,所以用单例模式将连接封装到getInstance(),这样做的好处是不用每次都去调用connect()方法,减少网络连接开销。PHP都是单线程同步执行的,所以整个程序只用实例化一个Redis对象即可。(来之《CleverCode的项目》)

4.2 需求分析

根据4.1可以分析出使用单例模式比较适合php网络连接的操作。如Mysql,Memcache,Redis,Gearman等都可以尝试单例模式。当然Mysql可能涉及到连接池,只需要将单例变成一个数组单例即可。即$_instance = null,变成$_instance = array(),$_instance[‘con1’] = new Self(‘conn1’);$_instance[‘con2’] = new Self(‘conn2’);

4.3 程序源码下载

http://download.csdn.net/detail/clevercode/8783989

4.4 程序说明

需要提前将Memcache与Redis加入到php扩展中。

1)单例模式设计Memcache操作类(MemcacheOperate.php)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php  
  
/** 
 * MemcacheOperate.php 
 * 
 * 单例模式设计Memcache操作类 
 * 
 * Copyright (c) 2015 http://blog.csdn.net/CleverCode 
 * 
 * modification history: 
 * -------------------- 
 * 2015/6/8, by CleverCode, Create 
 * 
 */  
class MemcacheOperate extends Memcache{  
      
    // 实例  
    protected static $_instance = null;  
  
    /** 
     * Singleton instance(获取自己的实例) 
     * 
     * @return MemcacheOperate 
     */  
    public static function getInstance(){  
        if (null === self::$_instance) {  
              
            self::$_instance = new self();  
            $host = $_SERVER['MEMCACHE_HOST'];  
            $port = $_SERVER['MEMCACHE_PORT'];  
            self::$_instance->addServer($host, $port);  
        }  
        return self::$_instance;  
    }  
}
 
2)单例模式设计Redis操作类(RedisOperate.php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php  
  
/** 
 * RedisOperate.php 
 * 
 * 单例模式设计Redis操作类 
 * 
 * Copyright (c) 2015 http://blog.csdn.net/CleverCode 
 * 
 * modification history: 
 * -------------------- 
 * 2015/6/8, by CleverCode, Create 
 * 
 */  
class RedisOperate extends Redis{  
      
    // 实例  
    protected static $_instance = null;  
  
    /** 
     * Singleton instance(获取自己的实例) 
     * 
     * @return RedisOperate 
     */  
    public static function getInstance(){  
        if (null === self::$_instance) {  
              
            self::$_instance = new self();  
            $host = $_SERVER['REDIS_HOST'];  
            $port = $_SERVER['REDIS_PORT'];  
            self::$_instance->connect($host, $port);  
        }  
        return self::$_instance;  
    }  
} 

3)客户端代码(singletonPattern.php)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<?php  
/** 
 * singletonPattern.php 
 * 
 * 单例模式 
 *  
 * Copyright (c) 2015 http://blog.csdn.net/CleverCode 
 * 
 * modification history: 
 * -------------------- 
 * 2015/6/8, by CleverCode, Create 
 * 
 */  
  
// 加载Memcache  
include_once ('MemcacheOperate.php');  
  
// 加载Redis  
include_once ('RedisOperate.php');  
  
/* 
 * 客户端类 
 * 让客户端和业务逻辑尽可能的分离,降低客户端和业务逻辑算法的耦合, 
 * 使业务逻辑的算法更具有可移植性 
 */  
class Client{  
  
    /** 
     * 初始化配置文件 
     * 
     * @return null 
     */  
    public static function initConfig(){  
        // Memcache 主机  
        $_SERVER['MEMCACHE_HOST'] = '192.168.6.201';  
          
        // Memcache 端口  
        $_SERVER['MEMCACHE_PORT'] = 11211;  
          
        // Redis 主机  
        $_SERVER['REDIS_HOST'] = '192.168.6.201';  
          
        // Redis 端口  
        $_SERVER['REDIS_PORT'] = 6379;  
    }  
  
    /** 
     * 主函数 
     * 
     * @return null 
     */  
    public function main(){  
        // 初始化配置  
        self::initConfig();  
          
        // Memcache key1  
        MemcacheOperate::getInstance()->set('key1', 'Memcache CleverCode1', 0, 100);  
        echo MemcacheOperate::getInstance()->get('key1');  
        echo "\r\n---\r\n";  
          
        // Memcache key2  
        MemcacheOperate::getInstance()->set('key2', 'Memcache CleverCode2', 0, 100);  
        echo MemcacheOperate::getInstance()->get('key2');  
        echo "\r\n---\r\n";  
          
        // Redis key3  
        RedisOperate::getInstance()->set('key3', 'Redis CleverCode3');  
        echo RedisOperate::getInstance()->get('key3');  
        echo "\r\n---\r\n";  
          
        // Redis key4  
        RedisOperate::getInstance()->set('key4', 'Redis CleverCode4');  
        echo RedisOperate::getInstance()->get('key4');  
        echo "\r\n---\r\n";  
    }  
}  
  
/** 
 * 程序入口 
 */  
function start(){  
    $client = new Client();  
    $client->main();  
}  
  
start();  
  
?>


4.5 程序运行结果展示

1
<img src="http://img.blog.csdn.net/20150608113823869?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQ2xldmVyQ29kZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

5 总结

5.1 优点

1
2
3
4
5
6
1)实例控制
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
 
 
2)灵活性
因为类控制了实例化过程,所以类可以灵活更改实例化过程。

5.2 缺点

1
2
3
4
5
6
7
8
9
10
1)开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
 
 
2)可能的开发混淆
使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
 
 
3)对象生存期
不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。
最后编辑:
作者:saunix
大型互联网公司linux系统运维攻城狮,专门担当消防员

留下一个回复