0

我被交给使用的代码库具有一个继承自MDB2的数据库类。这构成了使用中的 MVC 框架(自定义构建的事务)的基础,而模型又继承自 db。

我相信你们中的一些人已经注意到,这会导致一个相当大的问题。每次实例化模型时,都会创建一个新的数据库连接。这显然是相当浪费的。这也意味着我无法按预期使用事务,因为如果事务在模型的一个实例中开始,则在提交发生之前,其他实例将看不到它的影响。

我的计划是更改 db 类以封装 MDB2 而不是从其继承,然后让它通过其单例功能维护 MDB2 的单个实例。

然而,MDB2 是一个包含很多方法的大型库,代码库中的很多东西都依赖于能够访问 MDB2 方法。

有没有一种方法可以封装 MDB2 类并将调用传递给它,而无需修改更高层,并且不必为 MDB2 中的每个方法编写包装器方法?

4

1 回答 1

3

由于您尚未提供任何代码,因此这是一个盲目的建议,您可以使用很少的代码删除继承,同时保持完整的功能并确保 MDB 类只实例化一次。

class Db
{
    protected static $_mdb;
    public function __construct()
    {
        if(self::_mdb === NULL) {
            self::_mdb = new MDB;
        }
    }
    public function __call($method, $args)
    {
        return call_user_func_array(array(self::_mdb, $method), $args);
    }
}

这基本上将使您的 DB 类成为 MDB 的装饰器。在第一次实例化时,DB 类将创建并存储 MDB 的静态实例。这将在 DB 的任何实例之间共享,包括子类。这里没有理由使用单例。

拦截器将__call确保您在 DB 中调用的所有调用 MDB 方法的方法都将被捕获并委托给 MDB 实例。魔术方法可能会对性能产生严重影响,因此当您注意到任何性能影响时,请将任何调用的方法添加到 DB 类并从那里委托。

不用说,这仍然不是最好的解决方案,因为您的数据库实例仍然与您的模型类紧密耦合。如果你能负担得起更多的重构,我建议让当前从 DB 继承的所有类都封装 DB 实例(除非它们是 ActiveRecords)。然后使用依赖注入使数据库实例可用。

于 2010-11-22T11:14:01.330 回答