#php #oop #dependencies #instantiation #circular-dependency
Вопрос:
Я испытываю то, что, по моему мнению, является проблемой циклической зависимости с моим PHP-приложением. Пожалуйста, дайте мне знать, если это неверно. Вот такая ситуация:
Два класса, LogManager и DBSession.
DBSession используется для взаимодействия с базой данных, а LogManager используется для входа в файлы. Оба широко используются в моем приложении. Когда вы создаете экземпляр DBSession, вы должны предоставить ему экземпляр LogManager с помощью параметра конструктора. Это связано с тем, что DBSession иногда записывает информацию в файл и для этого использует экземпляр LogManager.
Теперь я хотел расширить LogManager, чтобы он также мог регистрироваться в таблице базы данных, а не в текстовом файле. Естественно, я предпочитаю повторно использовать существующие классы, но вскоре я понял, что это привело к интересной ситуации.
Для создания DBSession уже требуется экземпляр LogManager. Если я хочу повторно использовать класс DBSession в LogManager, теперь для этого потребуется экземпляр DBSession. Как я могу удовлетворить оба требования? Очевидно, что-то не так с моим подходом.
Как бы вы предложили мне это исправить?
Заранее спасибо, ребята.
Ответ №1:
Не расширяйте LogManager, пусть это будет агрегированный тип. И отложите выбор места, куда вы хотите войти, т. е.:
$logManager = new LogManager();
$dbSession = new DbSession($logManager);
$logManager->add(new FileLog($filename) );
$logManager->add(new DBLog($dbSession) );
Где, конечно, FileLog и DBLog имеют общий интерфейс.
Это приложение шаблона наблюдателя, где add () — это операция «подписаться», а журнал файлов/DBLog-наблюдатели за событиями регистрации.
(Таким образом, вы также можете сохранять журналы во многих местах.)
Оуэн правка: адаптирован к синтаксису php.
Комментарии:
1. $LogManager = новый логменеджер(); $dbSession = новая сессия базы данных($LogManager); $LogManager->добавить(новый файловый журнал($имя файла)); $LogManager->>добавить(новый блог($dbSession));
Ответ №2:
Один из этих объектов на самом деле не нуждается в другом: как вы уже догадались, это сеанс DBS. Измените этот объект, чтобы регистратор можно было прикрепить к нему после создания.
Ответ №3:
Зачем требовать объект LogManager для создания объекта DbSession, если он только иногда записывает в файлы? лениво загружайте его вместо этого только тогда, когда вам это нужно. Кроме того, на мой взгляд, оба должны быть независимы друг от друга. Каждый из них мог бы использовать другой, когда это необходимо.
Комментарии:
1. Никогда по-настоящему не пытался реализовать ленивую загрузку, но спасибо за рекомендацию. Я признаю, что это было бы более подходящим, учитывая, что LogManager только иногда используется с DBSession. Спасибо!
Ответ №4:
Возможно, вы можете применить какой-нибудь шаблон, например шаблон Одноэлементный, чтобы убедиться, что у вас есть только один экземпляр класса LogManager, например.