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

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

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

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


万马奔腾
1 声望0 粉丝