乐趣区

多例模式

上篇文章,我们说过了单例模式,有童鞋会问:有单例,是不是有多例?答案:是的,这篇文章,我们来聊一下多例模式。

多例模式,就是一个类有多个实例,而且该实例都是该类本身。这样的类叫做多例类,具有以下:

  • 多例类可以有多个实例。
  • 多例类必须自己创建、管理自己的实例,并向外界提供自己的实例。

简单啰嗦一句,跟普通我们 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 连接的处理就是用的单例模式。

退出移动版