【发布时间】:2014-04-15 00:57:12
【问题描述】:
考虑以下示例:
- 有一个 A 类,它纯粹是产生副作用的对象(例如记录分析数据)
- 这个 A 级很重。即你不想在一个进程中拥有超过 1 个。此类中的方法也是线程安全的。
- B 类执行一些业务逻辑。同样,C 类也存在,B 类使用它,C 也执行一些业务逻辑。
- B 和 C 都想使用 A 并执行这些副作用。
问题:组成这 3 个类的正确方法是什么?
选项一:
class B {
public B(A a) {
c = new C(a)
}
public Foo calcXX() {
// do something useful using C
a.doSideEffect(..)
return foo;
}
}
class C {
public C(A a) { ... }
public Bar calcBar() {
a.doSideEffect(...)
return bar;
}
}
选项 1 的缺点:
- 如果类 A 不是业务对象,而是像 Analytics 类或 Configuration 类那样更辅助,那么,Option-1 似乎会不必要地污染构造函数签名。
选项 2:
class B {
public B() {
a = A.getInstance()
}
public Foo calcXX() {
// do something useful using C
a.doSideEffect(..)
return foo;
}
}
class C {
public C() { a = A.getInstance() }
public Bar calcBar() {
a.doSideEffect(...)
return bar;
}
}
【问题讨论】:
-
只看代码而没有阅读您的帖子,我倾向于选项 1,因为它似乎不需要单例。
-
这些不是等价的。选项 2 包含用于查找您正在使用的 A 实例的代码。选项 1 要求调用代码找到该实例。选项 1 很可能有一个 A 的副本通过许多构造链,所以我认为选项 2 通常更好;但是,最好将 A 的函数转换为静态函数,这样您就不必担心任何 A 对象。
-
我更喜欢选项 1。您不会“不必要地”污染构造函数签名;两个类do 都需要被告知
A,最直接的和 灵活的方法是从外部传入它。隐藏对A的这种依赖可能会使您的构造函数签名看起来不那么复杂,但它不会使整体架构/设计变得不那么复杂,而且它确实使它不那么明显。
标签: design-patterns dependency-injection functional-programming object-oriented-analysis