上篇文章,我们说过了单例模式,有童鞋会问:有单例,是不是有多例?答案:是的,这篇文章,我们来聊一下多例模式。
多例模式,就是一个类有多个实例,而且该实例都是该类本身。这样的类叫做多例类,具有以下:
- 多例类可以有多个实例。
- 多例类必须自己创建、管理自己的实例,并向外界提供自己的实例。
简单啰嗦一句,跟普通我们new对象不一样,我们可以多次new对象,但是每次new的对象都是一个新的对象;而多例类里面所有的实例都是该类本身。
下面我们来看一下具体的代码实现:
逻辑:CD工厂要不不同的内容授权给不同的工厂去生产:把CD1的内容让工厂1生产;CD2的内容让工厂2生产。这样可以减少CD工厂的数量,增加CD工厂的扩展性。
class CDFactory{ /** * 实例对象数组 * * @var array */ private static $_instances = []; /** * 构造函数私有,防止类可以通过 new 实例化 * * @access private * @return void */ private function __construct () { } /** * 私有化复制克隆方法,防止类别复制和克隆 * * @access private * @return void */ private function __clone () { } /** * 阻止实例被序列化 * * @access private * @return void */ private function __wakeup () { } /** * 定义获取对象实例的入口,返回该实例 * * @access public * @param string $name 实例化名字 * @return self */ public static function getInstance (string $name) { // 判断是否已经存在实例化对象 if (!isset(self::$_instances[$name])) { p('new intance:' . __CLASS__); // 不存在,则实例化一个 self::$_instances[$name] = new self(); } return self::$_instances[$name]; } /** * 此接口用来测试单例模式 - 改变 string 的值 * * @access public * @param string $string 值 * @return void */ public function setContent($string) { $this->string = $string; } /** * 此接口用来测试单例模式 - 输出 string 的值 * * @access public * @return void */ public function getContent() { p('$this->string',$this->string); }}
调用的代码:
class Client{ static public function factory1Produce() { $cd = CDFactory::getInstance('CD1'); $cd->setContent('CD 1 内容~'); return $cd; } static public function factory2Produce() { $cd = CDFactory::getInstance('CD2'); $cd->setContent('CD 2 内容~'); return $cd; } /** * 主函数 */ static public function main() { //工厂1生产 $cd_1 = static::factory1Produce(); $cd_1->getContent(); //工厂2生产 $cd_2 = static::factory2Produce(); $cd_2->getContent(); }}
执行结果:
new intance:CDFactory$this->string=string(12) "CD 1 内容~"new intance:CDFactory$this->string=string(12) "CD 2 内容~"
执行结果里面我们可以看到,new intance:CDFactory调用了两次,实现了一个类有多个实例,因为我们的实例是存在 $_instances 数组中,所以每次new intance又都是CD类本身。
在实际应用中,多例模式可以用在处理多个数据库连接器等相似功能,但是不同实例的情况。
多例模式和单例模式是比较简单的设计模式,同时也是被经常使用的设计模式,尤其是单例模式,比如 ThinkPHP中的Cache就是用的多例模式,但是Redis连接的处理就是用的单例模式。