04 02 2020

多例模式

模式定义

多例模式和单例模式类似,但可以返回多个实例。比如我们有多个数据库连接,MySQL、SQLite、Postgres,又或者我们有多个日志记录器,分别用于记录调试信息和错误信息,这些都可以使用多例模式实现。

代码示例

Multion\Multion.class.php
<?php
namespace Multion;

abstract class Multion
{
    private static $instances = array();

    public static function getInstance()
    {
        $key = get_called_class() . serialize(func_get_args());
        if(!isset(self::$instances[$key])){
            $rc = new \ReflectionClass(get_called_class());
            self::$instances[$key] = $rc->newInstanceArgs(func_get_args());
        }
        return self::$instances[$key];
    }
}


Multion\Mysql.class.php
<?php
namespace Multion;

class Mysql extends Multion
{
    public function __construct($cfg)
    {
        echo serialize($cfg);
    }
}


Multion\Redis.class.php
<?php
namespace Multion;

class Redis extends Multion
{
    public function __construct($cfg)
    {
        echo serialize($cfg);
    }
}


Multion\MultionTest.php
<?php
spl_autoload_register(function ($className){
   $className = str_replace("\\", "/", $className);
   include $className . ".class.php";
});

use Multion\Mysql;
use Multion\Redis;

$instance1 = Mysql::getInstance(["db" => 'mysql', 'username' => 'test1', 'password' => 'secret']);
$instance2 = Mysql::getInstance(["db" => 'mysql', 'username' => 'test2', 'password' => 'secret']);
$instance3 = Mysql::getInstance(["db" => 'mysql', 'username' => 'test1', 'password' => 'secret']);
$instance4 = Redis::getInstance(["db" => 'Redis', 'username' => 'test4', 'password' => 'secret']);

echo "\n" . ($instance1 === $instance2 ? '相同' : '不同');
echo "\n" . ($instance1 === $instance3 ? '相同' : '不同');
echo "\n" . ($instance1 === $instance4 ? '相同' : '不同');


测试示例:

php Multion/MultionTest.php

输出:
不同
相同
不同



代码地址:https://github.com/798256478/design-patterns/tree/master/Multion