Модификация класса для инкапсуляции вместо наследования - PullRequest
0 голосов
/ 22 ноября 2010

Кодовая база, с которой я работал для работы, имеет класс базы данных, который наследуется от MDB2 .Это формирует основу для используемой инфраструктуры MVC (дело, построенное по индивидуальному заказу), а модели, в свою очередь, наследуются от db.

Как я уверен, некоторые из вас заметили, это приводит к довольно большой проблеме.Каждый раз, когда вы создаете экземпляр модели, в результате создается новое соединение с базой данных.Это очевидно довольно расточительно.Это также означает, что я не могу использовать транзакции по назначению, потому что если транзакция начинается в одном экземпляре модели, ее эффекты невидимы для других экземпляров, пока не произойдет фиксация.

Мой план состоит в том, чтобы изменитькласс db для инкапсуляции MDB2 вместо наследования от него, а затем для поддержки одного экземпляра MDB2 с помощью его одноэлементной функциональности.

Тем не менее, MDB2 - это большая библиотека с большим количеством методов, и многие вещи выше в базе кода зависят от возможности доступа к методам MDB2.

Есть ли способ инкапсулировать класс MDB2 и передавать ему вызовы без изменения более высоких уровней и без необходимости написания метода-оболочки для каждого метода в MDB2?

1 Ответ

3 голосов
/ 22 ноября 2010

Поскольку вы еще не предоставили никакого кода, это слепое предложение о том, как можно удалить наследование с помощью очень небольшого кода, в то же время поддерживая полную функциональность и следя за тем, чтобы класс 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.Это будет использоваться всеми экземплярами БД, включая дочерние классы.Здесь нет причин использовать Singleton.

Перехватчик __call обеспечит перехват всех методов, которые вы вызывали в DB и которые вызывают методы для метода MDB, и делегирование экземпляру MDB.Магические методы могут сильно повлиять на производительность, поэтому, когда вы заметите какое-либо влияние на производительность, добавьте все вызываемые методы в класс DB и делегируйте оттуда.

Нет необходимости говорить, что это все еще не лучшее решение, потому что вашеЭкземпляр БД все еще тесно связан с вашими модельными классами.Если вы можете позволить себе больше рефакторинга, я бы посоветовал сделать так, чтобы все классы, которые в настоящее время наследуются от БД, инкапсулировали экземпляр БД (если они не ActiveRecords).Затем используйте Dependency Injection, чтобы сделать экземпляр БД доступным.

...