我正在努力重构我编写的Java应用程序。在撰写原文时,我做了一些糟糕的设计决定,现在正在承受后果。特别是,代码几乎不可能进行单元测试,并且依赖性已经到处都是。
我一直在阅读有关设计模式和良好OO设计原则(包括SOLID)的大量内容。我认为解决我的问题的关键在于:构造函数依赖注入(理想情况下不是通过像Spring这样的框架;我宁愿坚持普通的旧Java),工厂,构建器和一般的OO设计。
没有太多细节,想象一下我有一个对象结构,其中O1有一个或多个O2子对象,每个O2对象有一个或多个O3子对象,依此类推。因此,基本上,O1是O2的父级,O2是O3的父级。 (但不是继承意义上的。)
我想要表示的依赖项属于父级的子级。因此,例如,将依赖项注入构造函数可能会导致类似这样的内容:
// highest-level object; no dependencies
O1 o1a = new O1();
// second-level objects; depend on highest-level object
O2 o2a = new O2(o1a);
O2 o2b = new O2(o1a);
// 3rd-level objects; depend on second-level objects
O3 o3a = new O3(o2a); // dependency on o2a
O3 o3b = new O3(o2a); // dependency on o2a
O3 o3c = new O3(o2b); // dependency on o2b
好的,所以这本身很简单。但是有一些复杂的因素:
在我所有的设计模式阅读中,遗憾的是,我从未见过如何像这样模糊地完成某些事情的例子。 (通过比较,所有例子都非常简单。)
我想知道为O3创建某种工厂或构建器,并为O2传递一个工厂或构建器的实例。反过来,O2工厂或构建器的实例将使用O1的工厂或构建器的实例创建。但我不确定这是否是正确的方法,即使是这样,我也很难超越高级概念。
我非常感谢有关如何以干净,可维护,可扩展的方式完成所有这些工作的一些指导。我知道,这是一个很高的订单。
提前致谢,
格雷格
答案 0 :(得分:2)
我开始时遇到的问题基本上和你一样。我想要一个纯Java"注射"没有魔法的解决方案,所以我创建了JayWire。即使您不打算使用此库,也可以查看Wiki的一些想法。
具体来说,基本思想是注入工厂(java.util.function.Supplier)而不是构造对象。这样,消费类不必每次都知道对象是单例,汇集还是构造(新的)。它是这样的:
public class O3 {
private Supplier<O2> o2Supplier;
public O3(Supplier<O2> o2Supplier) {
this.o2Supplier = o2Supplier;
}
public void doSomething() {
...
// Here O3 wants an O2 instance, but does not
// need to know how to construct it, or even
// whether its constructed, or the same instance
// is re-used.
O2 o2 = o2Supplier.get();
o2.doIt(...);
...
}
}
这种方式是隐藏&#34;隐藏&#34;来自O3,它只知道它需要O2,但并不一定需要知道O2是如何构建的。
您当然可以将供应商更改为工厂(或其他),尽管工厂暗示它将始终创建新实例。
你甚至可能在O2的构造中有一些本地的参数,但仍然想隐藏它需要来自消费者O3的O1这一事实。这也可以这样做:
public class O3 {
private Supplier2<String, Integer, O2> o2Supplier;
public O3(Supplier2<String, Integer, O2> o2Supplier) {
this.o2Supplier = o2Supplier;
}
public void doSomething() {
...
// Here O3 wants an O2 instance again, but also
// wants additional parameters for its construction.
O2 o2 = o2Supplier.get("Param1", 5);
o2.doIt(...);
...
}
}
Supplier2与供应商类似,它的get()方法只需要2个额外的参数。
这样,O3仍然不知道O2需要O1,因此可以分解层次结构。您可能希望查看&#34;传播依赖关系&#34;在Wiki中。
JayWire实现了这一切,并且还可以帮助您轻松创建这些供应商。