实用的Singleton&依赖注入问题 [英] Practical Singleton & Dependency Injection question

查看:90
本文介绍了实用的Singleton&依赖注入问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有一个名为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆