实用的Singleton&依赖注入问题 [英] Practical Singleton & Dependency Injection question
问题描述
说我有一个名为PermissionManager的类,该类对于我的系统只应存在一次,并且基本上可以实现管理应用程序中各种操作的各种权限的功能。现在,我的应用程序中有一些类,该类需要能够在其方法之一中检查某些权限。此类的构造函数当前是公共的,即由API用户使用。
Say I have a class called PermissionManager which should only exist once for my system and basically fulfills the function of managing various permissions for various actions in my application. Now I have some class in my application which needs to be able to check a certain permission in one of its methods. This class's constructor is currently public, i.e. used by API users.
直到几周前,我只是让我的类在某个地方调用以下伪代码:
Until a couple of weeks ago, I would have simply had my class call the following pseudo-code somewhere:
PermissionManager.getInstance().isReadPermissionEnabled(this)
但是,由于我注意到这里的每个人都讨厌单身人士+这种耦合,所以我想知道会有更好的解决方案,因为我对单身人士的论点似乎很有意义(不可测试,高耦合等)。
But since I have noticed everyone here hating singletons + this kind of coupling, I was wondering what the better solution would be, since the arguments I have read against singletons seem to make sense (not testable, high coupling, etc.).
所以我实际上应该要求API用户在类的构造函数中传递PermissionManager实例吗?即使我只希望我的应用程序存在一个PermissionManager实例?
So should I actually require API users to pass in a PermissionManager instance in the constructor of the class? Even though I only want a single PermissionManager instance to exist for my application?
还是我要解决所有这些错误,应该在某个地方有一个非公共构造函数和一个工厂
Or am I going about this all wrong and should have a non-public constructor and a factory somewhere which passes in the instance of PermissionManager for me?
其他信息,请注意,当我说依赖注入,我说的是DI 模式 ...我没有使用任何DI框架,例如Guice或Spring。 (...至今)
Additional info Note that when I say "Dependency Injection", I'm talking about the DI Pattern...I am not using any DI framework like Guice or Spring. (...yet)
推荐答案
如果您使用的是依赖项注入框架,那么通常的处理方法是可以在构造函数中传入PermissionsManager对象,或者具有框架为您设置的PermissionsManager类型的属性。
If you are using a dependency-injection framework, then the common way to handle this is to either pass in a PermissionsManager object in the constructor or to have a property of type PermissionsManager that the framework sets for you.
如果这不可行,那么让用户通过工厂获得此类的实例是一个不错的选择。在这种情况下,工厂在创建类时将PermissionManager传递给构造函数。在应用程序启动时,您将首先创建单个PermissionManager,然后创建工厂,并传入PermissionManager。
If this is not feasible, then having users get an instance of this class via factory is a good choice. In this case, the factory passes the PermissionManager in to the constructor when it creates the class. In your application start-up, you would create the single PermissionManager first, then create your factory, passing in the PermissionManager.
您正确的认为,通常对于类的客户知道在哪里可以找到正确的PermissionManager实例并将其传递(甚至关心您的类使用PermissionManager的事实)。
You are correct that it is normally unwieldy for the clients of a class to know where to find the correct PermissionManager instance and pass it in (or even to care about the fact that your class uses a PermissionManager).
一个折衷方案我见过的解决方案是为您的类提供PermissionManager类型的属性。如果已设置属性(例如,在单元测试中),则使用该实例,否则使用单例。
One compromise solution I've seen is to give your class a property of type PermissionManager. If the property has been set (say, in a unit test), you use that instance, otherwise you use the singleton. Something like:
PermissionManager mManager = null;
public PermissionManager Permissions
{
if (mManager == null)
{
return mManager;
}
return PermissionManager.getInstance();
}
当然,严格来说,您的PermissionManager应该实现某种IPermissionManager接口,并且这是您其他班级应该引用的内容,以便在测试过程中可以更轻松地替换虚拟实现。
Of course, strictly speaking, your PermissionManager should implement some kind of IPermissionManager interface, and that's what your other class should reference so a dummy implementation can be substituted more easily during testing.
这篇关于实用的Singleton&依赖注入问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!