Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 如何合成纯粹是副作用的对象?_Design Patterns_Dependency Injection_Functional Programming_Object Oriented Analysis - Fatal编程技术网

Design patterns 如何合成纯粹是副作用的对象?

Design patterns 如何合成纯粹是副作用的对象?,design-patterns,dependency-injection,functional-programming,object-oriented-analysis,Design Patterns,Dependency Injection,Functional Programming,Object Oriented Analysis,考虑以下示例: 有一个类别a纯粹是产生副作用的对象(比如说,记录分析数据) 这个A级很重。i、 e.您不希望在一个流程中拥有超过1个。此类中的方法也是线程安全的 B类执行一些业务逻辑。类似地,C类也存在,B类使用C类,C类也执行一些业务逻辑 B和C都希望使用A并执行这些副作用 问题:组成这三门课的正确方法是什么 备选案文1: B类{ 公共图书馆B(A){ c=新的c(a) } public Foo calcXX(){ //使用C做一些有用的事情 a、 剂量效应(……) 返回foo; } } C类

考虑以下示例:

  • 有一个类别a纯粹是产生副作用的对象(比如说,记录分析数据)
  • 这个A级很重。i、 e.您不希望在一个流程中拥有超过1个。此类中的方法也是线程安全的
  • B类执行一些业务逻辑。类似地,C类也存在,B类使用C类,C类也执行一些业务逻辑
  • B和C都希望使用A并执行这些副作用
  • 问题:组成这三门课的正确方法是什么

    备选案文1:

    B类{
    公共图书馆B(A){
    c=新的c(a)
    }
    public Foo calcXX(){
    //使用C做一些有用的事情
    a、 剂量效应(……)
    返回foo;
    }
    }
    C类{
    公共C(A){…}
    公共酒吧calcBar(){
    a、 剂量效应(…)
    返回杆;
    }
    }
    
    方案1的缺点:

  • 如果类A不是业务对象,而是像分析类或配置类这样的辅助类,那么选项1似乎会不必要地污染构造函数签名
  • 备选案文2:

    B类{
    公共图书馆B(){
    a=a.getInstance()
    }
    public Foo calcXX(){
    //使用C做一些有用的事情
    a、 剂量效应(……)
    返回foo;
    }
    }
    C类{
    公共C(){a=a.getInstance()}
    公共酒吧calcBar(){
    a、 剂量效应(…)
    返回杆;
    }
    }
    
    这里建议的选项没有一个特别好

  • 第一个选项(稍微)违反了这一点。特定的罪犯是
    B
    的构造函数,它创建了一个新的
    C
    。如果
    B
    需要
    C
    的实例,则应在其构造函数中声明该实例
  • 第一个选项利用了单例模式,这可能是合适的,但隐藏了客户机的依赖关系,并且倾向于使重用消费类变得更困难(因此也使它们更难进行单元测试)
  • 更好的选择是:

    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
    无关

    您现在可以像这样组合
    B
    C
    的实例:

    a = new A()
    c = new C(a)
    b = new B(a, c)
    
    请注意,
    A
    的同一个实例同时被
    b
    c
    使用


    有关高效图形组合的更多信息,请参见

    在没有阅读您的帖子的情况下查看代码,我倾向于选项1,因为它似乎不需要单例。这些选项并不等效。选项2包含查找您正在使用的实例的代码。选项1要求调用代码找到该实例。方案1很可能有一个通过众多建筑链的副本,因此我认为方案2通常更好;然而,最好的方法是将A的函数转换成静态函数,这样您就不必担心任何A对象了。我赞成选项1。您没有“不必要地”污染构造函数签名;这两个类都需要被告知
    A
    ,最直接、最灵活的方法是从外部传入。将此依赖项隐藏在
    A
    上可能会使构造函数签名看起来不那么复杂,但它不会使整个体系结构/设计变得不那么复杂,而且确实会使其不那么明显。