用于在Rational和Reals之间进行转换的API设计

时间:2013-12-15 22:49:36

标签: java design-patterns stl factory-pattern

我有一个设计模式问题: - 假设我必须设计一个具有以下类的Math库:Real和Rational。

将以下方法添加到库中的最佳设计模式是什么:

  • 近乎真实的理性
  • 将理性转换为真实
  • 简化有理数
  • 有理数的中位数

我可以看到几种方法。

方法-1:

  • 添加real.toRational()/ Rational.fromReal(),rational.toReal(),rational.simplify(),rational.mediant()

方法-2:

  • 将它们作为静态因子方法添加到类NumberFactory中,例如:Operations.real2Rational(),Operations.rational2Real(),Operational.simplifyRational(),Operations.mediant()

每种方法的优点/缺点是什么?我的看法如下: -

方法-1优点:

  • 方法名称更简洁。
  • 更好的OO封装

方法-1缺点:

  • Classes Real和Rational现在使用所有这些转换器和实用程序方法膨胀

方法-2优点:

  • Real和Rational类保持简洁,并且对其他类的依赖性最小化。
  • 易于记忆:库用户将确定所有方法都在一个名为NumberFactory的类中

方法-2缺点:

  • 似乎少了OO'ish。

2 个答案:

答案 0 :(得分:0)

我多年没有使用这些术语,所以也许我记错了,但不是全部Rational数字Real?在这种情况下,Rational 是A Real,因此Rational应该是Real的子类。

因此,您的第一种方法可能是最好的:

为简单起见,我们假装Real包含double的值。

public class Real{

  private final double value;

  public double getValue(){
      return value;
  }

}

Rational类有更有趣的方法。由于它是Real的子类,它仍然会有getValue()方法返回一个double,因此您不再需要toReal()转换器方法。

由于有理数可以表示为分数,因此也应该将分子和分母与吸气剂一起存储。

public class Rational extends Real{
     private final long numerator,denominator;

     ....
     public long getNumerator(){ ..}

     public long getDenominator(){ ..}

}

简化只是修改分子和分母(但是相同的实数值)。好的API应该使用不可变对象,mutator方法应该返回新的实例,所以我们可以像这样添加我们的简化方法:

public Rational extends Real{

       ...

   public Rational simplify(){
      //check if we are already simplified
      //if so return this
      if(alreadySimplified()){
           return this;
      }
      return new Rational(value, reducedNum, reducedDenom);


   }
}

Mediant可以是Rational中的一个方法,它将第二个Rational作为参数,或者静态实用程序类中的方法需要2 Rational个。我会把它留给你,但不管怎样,你应该返回新的实例,而不是改变现有的值。

API设计中最有趣的部分是如何将Real转换为Rational?如果Rational尚未Real,是否应该使用一种近似Rational的方法?而不是抛出异常的方法?您如何知道您的Real实例是否实际上是Rational子类? (也许是isRational()方法?或者使用instanceof check?我会把它留给你。

答案 1 :(得分:0)

查看Java API并从中获得灵感。 您的课程RationalReal可能会以与NumberInteger类似的方式扩展Double课程。这是一个非常相似的关系案例。