Інші дуже добре пояснили проблему з одинаками взагалі. Я просто хотів би додати примітку щодо конкретного випадку Logger. Я погоджуюсь з вами, що, як правило, не проблема отримати доступ до реєстратора (або, точніше, до кореневого реєстратора) як одиночний за допомогою статичного методу getInstance()
або getRootLogger()
методу. (якщо ви не хочете побачити, що реєструється класом, який ви тестуєте, - але на моєму досвіді я навряд чи можу згадати такі випадки, коли це було необхідно. Знову ж таки, для інших це може бути більш актуальною проблемою).
ІМО, як правило, одномантовий реєстратор не турбує, оскільки він не містить жодного стану, що відповідає класу, який ви тестуєте. Тобто стан реєстратора (та його можливі зміни) ніяк не впливає на стан тестованого класу. Отже, це не ускладнює ваші модульні тести.
Альтернативою може бути введення реєстратора за допомогою конструктора для (майже) кожного окремого класу у вашому додатку. Для узгодженості інтерфейсів його слід вводити, навіть якщо відповідний клас на даний момент нічого не реєструє - альтернативою може бути те, що коли в якийсь момент ви виявляєте, що зараз вам потрібно щось записати з цього класу, вам потрібен реєстратор, таким чином Вам потрібно додати параметр конструктора для DI, порушуючи весь клієнтський код. Мені не подобаються обидва ці варіанти, і я відчуваю, що використання DI для лісозаготівлі просто ускладнило б моє життя з метою дотримання теоретичного правила без будь-якої конкретної вигоди.
Отже, мій підсумок: клас, який використовується (майже) універсально, але не містить стану, що стосується вашої програми, може бути сміливо реалізований як Singleton .