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

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

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

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