如何组成纯粹副作用的对象?

时间:2014-04-15 00:57:12

标签: design-patterns dependency-injection functional-programming object-oriented-analysis

考虑以下示例:

  1. 有一个A类纯粹是一个副作用产生对象(例如,记录分析数据让我们说)
  2. 这个A级很重。即你不希望在一个过程中拥有超过1个。此类中的方法也是线程安全的。
  3. B类做一些业务逻辑。类似地,类C也存在,B类使用它,C也有一些业务逻辑。
  4. B和C都想使用A并执行这些副作用。
  5. 问题:撰写这3个班级的正确方法是什么?

    选项-1:

    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. 选项-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 个答案:

答案 0 :(得分:3)

此处建议的选项都不是特别好。

  1. 第一个选项(略有)违反了Nikola Malovic's 4th Law of IoCInjection Constructors should be simple。具体的罪犯是B的构造函数,它会创建一个新的C。如果B需要C的实例,则应在其构造函数中声明该实例。
  2. 第一个选项使用Singleton模式,可以是合适的,但隐藏了客户端的依赖关系,并且往往会使重用消耗类变得更加困难(从而也使得它们更难以单元化检验)。
  3. 更好的选择是:

    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)
    

    请注意,Ab同时使用c的同一个实例。

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