所以我最近被添加到一个工作中的新项目中,Java 代码有大约 10-15 个 Singleton 类,它们在任何地方都在使用。这些类的目的是从服务器获取数据(当客户端应用程序启动时)并使该数据在整个程序中都可以访问,这样就不必在每次需要时都进行服务调用,这在我看来是有道理的。
然而,在阅读了许多关于单例有多糟糕的帖子后,由于紧密耦合和不可测试,我将如何替换它们?有人告诉我依赖注入,但我真的想继续将相同的数据传递给应用程序中的几乎每个对象吗?任何建议都是有用的。
所以我最近被添加到一个工作中的新项目中,Java 代码有大约 10-15 个 Singleton 类,它们在任何地方都在使用。这些类的目的是从服务器获取数据(当客户端应用程序启动时)并使该数据在整个程序中都可以访问,这样就不必在每次需要时都进行服务调用,这在我看来是有道理的。
然而,在阅读了许多关于单例有多糟糕的帖子后,由于紧密耦合和不可测试,我将如何替换它们?有人告诉我依赖注入,但我真的想继续将相同的数据传递给应用程序中的几乎每个对象吗?任何建议都是有用的。
在这种情况下,我使用依赖注入 (DI),但正如您所说,您不喜欢它。
接下来我能想到的是 FACADE 模式,创建一个 ApplicationFacade 类并在需要的地方进行 DI。(如果你真的不喜欢 DI,也可以将其设为静态)
我相信这取决于每个单身人士。例如,Singleton 可以分解成几个静态函数吗?或者它可以分解成几个更小的类。也许它只用于应用程序的一小部分;因此,重构了一个较小的类以在该模块中使用。我认为,归根结底,这取决于每个 Singleton 的使用情况。如果它使您的代码更简单、更可扩展、更简洁等,请保留它;如果没有,请重构。
编辑:补充一下,需要重构什么?代码是否简单、干净并且有效?如果是这样,那么只需向应用程序添加功能即可。始终寻求添加代码/功能,而不是修改现有代码。最后你要回答,它是可扩展的吗?
看看古斯。您将构造函数定义为仅采用直接依赖项(没有工厂的工厂向下传递深层依赖项),用注释每个可注入构造函数,@inject
然后创建“模块”类,这些类定义用于那些中使用的任何抽象类或接口的实现构造函数。
Guice 将使用反射魔法根据模块类中的指令找到实现并实例化您的对象图。它甚至足够聪明,可以自动使用无参数构造函数来处理您没有在模块中明确定义的依赖项,而无需您明确告知它。
You can let Guice get much more entwined into your architecture than that, but if all you want to avoid is a chain of factories for injecting dependencies, then a little Guice is pretty nice.
The way you could design your classes is with explicit dependencies factored out. If a class uses a singleton:
class Client {
public void Method() {
SomeService.getInstance().doSomething();
}
}
It's hiding that dependency inside. To pull it out, (1) take it on construction or (2) on the involved method, if it makes sense (showing option 2):
class Client {
public void Method(SomeService service) {
service.doSomething();
}
}
This is the first step. Later, you could extract an interface from the singleton and use it. This is a slow process: refactor, retest, iterate...