【问题标题】:Object oriented code for populating a value object用于填充值对象的面向对象代码
【发布时间】:2012-12-21 11:47:09
【问题描述】:

这是一个低级设计问题。我正在尝试掌握面向对象的编程。

我正在编写一个 Java 类,该类具有设置值对象的数据成员值的方法。这些值是由我的班级根据一些业务逻辑计算的。最后,我的类应该返回如此填充的值对象。这样做最面向对象的方式是什么?

一种可能的方法,我似乎要走的路是,在我的 Java 类中为我需要设置的每个数据成员(VO)创建 compute() 方法。这些计算方法中的每一个都返回我使用值对象的相应 setter 方法设置的所需值。 但是,我认为这种方法比面向对象的方法更程序化,因为我只是按顺序按程序调用这些计算方法并填充我的值对象。

那么我可以使用/查看哪些设计(...设计模式?)或最佳实践,以使这段代码成为面向对象的。

代表代码(我现在有的):

class Adapter {   // this is my Java class
    MyValueObject applyBusinessLogic(Input object)
    {
        MyValueObject vo = new MyValueObject();
        vo.setA(computeA());
        vo.setB(computeB());
        vo.setC(computeC());
        return vo;
    }

    String computeA() { ...some logic... return a;}
    String computeB() { ...some logic... return b;}
    String computeC() { ...some logic... return c;}
}

class MyValueObject {
      String a;
      String b;
      String c;

      public void setA(String a)
      {
           this.a = a;
      }

      public void setB(String b)
      {
           this.b = b;
      }

      public void setC(String c)
      {
           this.c = c;
      }
}

【问题讨论】:

  • 你可以看看Builder模式en.wikipedia.org/wiki/Builder_pattern
  • “什么是最面向对象的做法?” - 没有像最面向对象的做法这样的事情。所以我想知道你为什么这样问。
  • @hakre 我的意思是什么是制作这个面向对象的过程代码的方法。

标签: java oop procedural-programming


【解决方案1】:

恕我直言,这真的取决于职责和计算方法的作用。您应该牢记 SRP (http://en.wikipedia.org/wiki/Single_responsibility_principle) 来进行 OO 设计。还有高内聚和松耦合原则。

如果 computeA()、B 和 C 不相关,则应拆分您的 Adapter 类。如果它们是相关的,那么您的 Adapter 类应该以不同的方式命名以表达它的实际作用。例如:税务计算器。

然后你可以创建一个新的类来接收一个 TaxCalculator 和一个 MyValueObject 来应用。或者只是将应用程序留在计算器中(尽管一个类需要两个职责,这通常很糟糕)。在后一种情况下,也许您可​​以调用类 TaxCalculationsSetter 或类似的东西,并将计算方法设为私有。等等,你会再次满足 SRP。 ;-)

请始终牢记,“什么是责任”是一个有点主观的东西。

我希望这已经澄清了一些事情。

【讨论】:

  • 顺便说一句:连续调用三个方法不是程序性的,也不是 OO。就是这样:一个接一个地调用三个方法。
  • 我的值对象的一些数据成员是我也需要计算的类本身的对象。我相信尝试将我的适配器拆分为一些辅助实用程序可能会有所帮助。有些只能创建这些子对象,我想我可以创建一些来完成所有类似任务。将尝试尽快更新它的工作原理。谢谢。
  • 您也应该尝试 TDD(如果还没有这样做的话)它使解决此类设计问题变得更加容易和自然。
【解决方案2】:

正如 izaera 已经提到的,这在很大程度上取决于您未提供的细节或问题。但是,至少有一件事我觉得不对:

您的值对象的构造似乎需要一些逻辑。现在的问题是,它应该去哪里?您已经在适配器中完成了它。但是,这可能不对,因为VO的构造属于VO而不是Adapter。因此,我肯定会将该逻辑移至 VO 本身 - 作为其构造的一部分。

因此,在我看来,将该逻辑移至 VO 会改进设计。

...
MyValueObject vo = new MyValueObject(); 
vo.setA(required input);
vo.setB(required input);
vo.setC(required input);

class MyValueObject {
      String a;
      String b;
      String c;

      public void setA(required input)
      {  
          ... some logic
          this.a = result of logic
      }

      public void setB(required input)
      {  
          ... some logic
          this.b = result of logic
      }

      public void setC(Srequired input)
      {
             ... some logic
          this.c = result of logic
      }
}

显然,如果使用构造器立即完成构造,整个事情会变得更好,除非你必须使用设置器,如果说,你正在使用一些 ORM 等。

【讨论】:

  • 有趣。但这难道不是意味着 MyValueObject 类现在变得复杂了——它不再遵循 SRP 了吗?每个属性 a、b、c 等的计算都是复杂的,有些需要服务调用。
  • 仍然沿着您建议的路线前进,我在考虑是否应该扩展 MyValueObject 类并重载子类中的 setter/getter,我可以在其中进行所有复杂的计算。这样,子类只对属性进行计算,而超类只是一个普通的旧值对象。最后我可以返回子类的全部熟化实例,但由超类的引用 - MyValueObject 引用。那怎么样?
  • 不幸的是,我可以提供更多关于设计细节的意见,因为我没有足够的信息。但是,将逻辑移动到客户端类并不会降低其复杂性。如果您认为它很复杂,请考虑将其分解为模块的方法。但同样,模块应该在逻辑上有意义,而不是随机分解代码。
【解决方案3】:

对我来说看起来不错。您不应该总是寻找要使用的编程模式。最重要的是 KISS(保持愚蠢和简单)

我会考虑是否可以将 MyValueObject 设为不可变。

class Adapter {   // this is my Java class
    MyValueObject applyBusinessLogic(Input object){
        return new MyValueObject(computeA(),computeB(),computeC());
    }

    String computeA() { ...some logic... return a;}
    String computeB() { ...some logic... return b;}
    String computeC() { ...some logic... return c;}
}

class MyValueObject {
    final String a;
    final String b;
    final String c;

    public MyValueObject(String a, String b, String c){
        this.a=a;
        this.b=b;
        this.c=c;
    }

}

【讨论】:

    猜你喜欢
    • 2022-12-30
    • 2020-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多