【问题标题】:How to compose objects that are purely side effects?如何组合纯粹是副作用的对象?
【发布时间】:2014-04-15 00:57:12
【问题描述】:

考虑以下示例:

  1. 有一个 A 类,它纯粹是产生副作用的对象(例如记录分析数据)
  2. 这个 A 级很重。即你不想在一个进程中拥有超过 1 个。此类中的方法也是线程安全的。
  3. B 类执行一些业务逻辑。同样,C 类也存在,B 类使用它,C 也执行一些业务逻辑。
  4. 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 的缺点:

  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


【解决方案1】:

这里建议的选项都不是特别好的。

  1. 第一个选项(稍微)违反了Nikola Malovic's 4th Law of IoCInjection Constructors should be simple。具体的冒犯者是B 的构造函数,它创建了一个新的C。如果B 需要C 的实例,它应该在其构造函数中声明。
  2. 第一个选项利用单例模式,可能是合适的,但隐藏了客户端的依赖关系,并且往往使重用消费类变得更加困难(从而也使得它们更难组合测试)。

更好的选择是:

class B {
    public B(A a, C c) { }
    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;
    }
}

C 也使用A 的事实与B 无关。

您现在可以像这样编写BC 的实例:

a = new A()
c = new C(a)
b = new B(a, c)

请注意,bc 正在使用相同的 A 实例。

有关高效图组合的更多信息,请参阅http://blog.ploeh.dk/2011/03/04/Composeobjectgraphswithconfidence

【讨论】:

    猜你喜欢
    • 2010-09-22
    • 1970-01-01
    • 2015-11-25
    • 1970-01-01
    • 1970-01-01
    • 2019-06-20
    • 1970-01-01
    • 2011-08-14
    • 2012-01-02
    相关资源
    最近更新 更多