Прежде всего следует убедиться, что зависимость Logger предоставляется пользователем в любом случае. Предположительно, в первом случае конструктор для FileNameLoader принимает параметр Logger&
?
Ни в коем случае я ни при каких обстоятельствах не сделаю Регистратор Синглтоном. Никогда, никогда, ни как, ни как. Это либо внедренная зависимость, либо у вас есть функция Log
free, либо, если вам абсолютно необходимо, использовать глобальную ссылку на объект std::ostream
в качестве универсального регистратора по умолчанию. Класс Singleton Logger - это способ создания препятствий для тестирования без какой-либо практической выгоды. Так что, если какая-то программа создаст два объекта Logger? Почему это даже плохо, не говоря уже о том, чтобы создавать проблемы для себя, чтобы предотвратить? Первое, что я делаю в любой сложной системе ведения журналов, - это создание PrefixLogger, который реализует интерфейс Logger, но печатает указанную строку в начале всех сообщений, чтобы показать некоторый контекст. Singleton несовместим с такой динамической гибкостью.
Во-вторых, спросите, не захотят ли пользователи иметь один FileNameLoader, и вызовите LoadFileNames несколько раз, с одним регистратором в первый раз и другим регистратором во второй раз.
Если это так, то вам определенно нужен параметр Logger для вызова функции, потому что средство доступа для изменения текущего Logger (а) не является отличным API и (б) невозможно со ссылочным членом в любом случае: вы бы получили изменить на указатель. Возможно, вы могли бы сделать параметр регистратора указателем со значением по умолчанию 0
, хотя значение 0
означает «использовать переменную-член». Это позволит использовать, когда пользовательский код начальной настройки знает и заботится о ведении журнала, но затем этот код передает объект FileNameLoader другому коду, который будет вызывать LoadFileNames, но не знает или не заботится о ведении журнала.
Если нет, то зависимость Logger является инвариантом для каждого экземпляра класса, и использование переменной-члена вполне допустимо. Я всегда немного беспокоюсь о ссылочных переменных-членах, но по причинам, не связанным с этим выбором.
[Изменить относительно Строителя: я думаю, что вы можете найти и заменить в моем ответе, и он все еще остается в силе. Принципиальное различие заключается в том, является ли «Строитель, используемый этим объектом FileNameLoader» инвариантным для данного объекта, или же «Строитель, используемый в вызове» - это то, что звонящие в LoadFileNames должны настраивать для каждого вызова отдельно.
Возможно, я немного менее непреклонен, что Строитель не должен быть Синглтоном. Слегка. Могущество.]