2008-10-29 1 views
15

Скажем, у меня есть класс PermissionManager, который должен существовать только один раз для моей системы и в основном выполняет функцию управления различными разрешениями для различных действий в моем приложении. Теперь у меня есть некоторый класс в моем приложении, который должен иметь возможность проверять определенное разрешение в одном из своих методов. Конструктор этого класса в настоящее время является общедоступным, т. Е. Используется пользователями API.Практический вопрос о закачке Singleton & Dependency Injection

До пару недель назад, я бы просто был мой класс назвать следующие псевдо-код где-то:

 PermissionManager.getInstance().isReadPermissionEnabled(this) 

Но так как я заметил, что все здесь ненавидя одиночек + этот вид связи, я был интересно, какое лучшее решение было бы, поскольку аргументы, которые я прочитал против синглтонов, кажутся имеющими смысл (не проверяемый, высокая связь и т. д.).

Должен ли я действительно требовать от пользователей API передать экземпляр PermissionManager в конструкторе класса? Хотя мне нужен только один экземпляр PermissionManager для моего приложения?

Или я все об этом ошибаюсь и должен иметь непубличный конструктор и фабрику где-нибудь, которая проходит в экземпляре PermissionManager для меня?


Дополнительная информация Обратите внимание, что, когда я говорю «Dependency Injection», я говорю о DI Pattern ... Я не использую любые рамки DI как Guice или весной. (... все же)

ответ

3

Если вы используете фреймворк зависимости, тогда общий способ справиться с этим состоит в том, чтобы либо передать объект PermissionsManager в конструкторе, либо иметь свойство типа PermissionsManager, которое устанавливает для вас инфраструктура.

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

Вы правы, что для клиентов класса обычно неудобно знать, где найти правильный экземпляр PermissionManager и передать его (или даже заботиться о том, что ваш класс использует PermissionManager).

Одно компромиссное решение, которое я видел, - дать вашему классу свойство типа PermissionManager. Если свойство было установлено (например, в единичном тесте), вы используете этот экземпляр, иначе вы используете синглтон. Что-то вроде:

PermissionManager mManager = null; 
public PermissionManager Permissions 
{ 
    if (mManager == null) 
    { 
    return mManager; 
    } 
    return PermissionManager.getInstance(); 
} 

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

+1

Вопрос о инъекции через интерфейс является важным. Возможность издеваться над объектом PermissionManager в тестах - это то, что делает DI мощным подходом для более тестируемого кода. – 2008-10-29 14:53:40

0

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

В этом случае я сделаю PermissionManager статическим классом, если по какой-либо причине вам не понадобится быть не поддающимся проверке типу.

2

Вы действительно можете начать с ввода PermissionManager. Это сделает ваш класс более проверенным.

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

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

2

Если вы подписываетесь на способ инъекции зависимостей, независимо от того, какие классы необходимы вашему PermissionManager, он должен быть введен как экземпляр объекта. Механизм, который контролирует его создание (для обеспечения синергетического характера), работает на более высоком уровне. Если вы используете инфраструктуру инъекций зависимостей, такую ​​как Guice, она может выполнять работу по обеспечению соблюдения. Если вы выполняете проводку объектов вручную, инъекция зависимостей помогает группировать код, который делает экземпляр (работу нового оператора) подальше от вашей бизнес-логики.

В любом случае, классический синглтон «capital-S» обычно рассматривается как анти-шаблон в контексте инъекции зависимости.

Эти должности были проницательный для меня в прошлом:

1

Так я должен на самом деле требуют от пользователей API для передачи в экземпляре PermissionManager в конструкторе класса? Хотя мне нужен только один экземпляр PermissionManager для моего приложения?

Да, это все, что вам нужно. Независимо от того, является ли зависимость одноточечным/на запрос/на поток или фабричным методом, ответственность за ваш контейнер и его конфигурацию. В мире .net мы в идеале должны были бы зависеть от интерфейса IPermissionsManager для дальнейшего уменьшения связи, я полагаю, что это и лучшая практика на Java.

 Смежные вопросы

  • Нет связанных вопросов^_^