3

我的问题涉及 OOP 中的类设计。假设我们有 ItemBase,它是 Canceled、Modified 和 Additional 类的父类。我们还有 DueToBase 类——Provider 和 Distributor 的父类。


简单图


ItemBase 可能会因 DueToBase 类而改变。

假设 ItemBase 具有 DueToBase 类型的属性,而 DueToBase 具有称为 compute() 的接口方法。计算算法与特定的ItemBase派生类相关。所以我们有六种不同的可能的 ItemBase-DueToBase 关系组合。

例子。

ItemBase ib = new Added();
ib.changed = new Provider(ib);
ib.changed.compute();

我的问题是如何在真正的面向对象编程中构建 ItemBase 和 DueToBase 之间的关系?我没有在计算方法中看到 swich/case 或 if 条件子句来检查 ItemBase 是哪种类型的实例。如果 DueToBase 有另一个 XXXBase 类,其中有另一个接口方法 YYY() ,则情况会变得更糟,该方法依赖于 DueToBase 的特定实例(甚至依赖于 ItemBase)。如何处理此类情况?这些事情有什么好的编程模式吗?也许我遵循的方向很糟糕。我会很感激你的帮助。

也许我的图表不清楚。问题在于以下...伪代码:

doSomething(){
   if(itemBase instanceof Cancelled){
      if(dueToBase instanceof Provider)
         algorithm1();
      else if(dueToBase instanceof Company)
         algorithm2();
   }else if(itemBase instanceof Modified){
      if(dueToBase instanceof Provider)
         algorithm3();
      else if(dueToBase instanceof Company)
         algorithm4();
   }else if(itemBase instanceof Added){
      if(dueToBase instanceof Provider)
         algorithm5();
      else if(dueToBase instanceof Company)
         algorithm6();
   }
}

如果使用更深的 if 子句,情况会变得更糟。

4

4 回答 4

4

你的ItemBase类可以是一个包含compute()方法的抽象类,所有子类都可以有自己的实现。

所以以后你可以做这样的事情,

ItemBase ib = new Added();
ib.changed = new Provider(ib);
ib.changed.compute();

现在,当您调用计算方法时ib.changed,它将执行Added类的计算实现。


在您的情况下,由于基类,添加一个区分Provider和的实例变量Company。像boolean旗帜或int.

dueToBase instanceof Provider然后,您可以创建 if 语句,而不是使用。所以你更新的伪代码将减少到几行。像这样的东西,

doSomething(){
      if(dueToBase.isProvider) {
         algorithm1(); //execute if Provider
      } else { 
         algorithm2(); //execute if Company
      }
}

现在选择计算的复杂性将由抽象模式处理,然后您只需要担心它是公司还是提供商。

于 2012-07-18T23:45:41.217 回答
1

我会说策略模式

abstract class ItemBase {
  public DueToBase myDueToBase;
  public void partOfTheAlgorithmThatOnlySpecificIBKnows();
}

class Modified extends ItemBase {
  public void partOfTheAlgorithmThatOnlySpecificIBKnows() {
     //stuff only Modified knows
  }
}


abstract class DueToBase {
    public void partOfTheAlgorithmThatOnlySpecificDTBKnows();
}

class Provider extends DueToBase {
 //relevant code
  public ItemBase myItemBase;
  public void partOfTheAlgorithmThatOnlySpecificDTBKnows(){
       //stuff only provider knows
  }

  public void compute() {
       //you can also pass this but pointless since you all ready have the reference
       myItemBase.partOfTheAlgorithmThatOnlySpecificIBKnows();
       //some more code
  }
}

ItemBase ib = new Added();
ib.changed = new Provider(ib);
ib.changed.compute();

在示例中,这将调用:

1. compute on Provider
2. part of the algorithm that Modified knows how to calculate
3. rest of the code for the algorithm

因此,在compute函数中,您拥有继承类所需的所有特定方法,并且您可以改变compute()函数中的算法。

如果这不能解决您的问题,您可能只需要按照 Owl 所说的那样考虑需求的新设计。


也没有 ifs,但有更多的方法可以让你对 ifs 做同样的事情,你只是让继承机制为你做这件事。

于 2012-07-19T00:37:12.203 回答
1

你可以这样做:

interface Algorithm {
    void executeAlgorithm(DueToBase dueToBase);
}

并有地图

Map<Class, Algorithm> algorithmMap = new HashMap<Class, Algorithm>();

每个算法都有课程

例如:

/**
  * this class is, for example, when itemBase instanceof Cancelled 
  */
class Algorithm1 implements Algorithm {

    public void executeAlgorithm(DueToBase dueToBase) {
        if ( dueToBase instanceof Provider ) {
            someAlgorithm();  // the algorithm specified somewhere, for provider
        } else if ( dueToBase instanceof Company ) {
            anotherAlgorithm(); // the algorithm or Company.
    }

    // this someAlgorithm() and anotherAlgorithm() are not same for different Algorithm classes
}

您必须在某个地方构建 algorithmMap。

algorithmMap.add( Cancelled.class , new Algorithm1() );
algorithmMap.add( Modified.class , new Algorithm2() );
algorithmMap.add( Added.class , new Algorithm3() );

在 doSomething 方法中,您不必编写 if-else 块

doSomething() {
    Algorithm algorithm = algorithmMap.get( itemBase.getClass() );

    algorithm.executeAlgorithm(dueToBase);
}

在我看来,这是这个问题的一个很好的 oop 解决方案。

于 2014-05-30T13:32:37.893 回答
1

更好的方法是:

interface Algorithm {

    void executeAlgorithm();

}

并具有实现算法接口的类,而不是函数。算法 1、算法 2、算法 3 等等。

并有表:

Algorithm[,] algorithmTable = { { new Algorithm1(), new Algorithm2() },
                                { new Algorithm3(), new Algorithm4() },
                                { new Algorithm5(), new Algorithm6() }
                              };

并有地图

Map< Class<?> , Integer > itemBaseMap = new HashMap<>();

Map< Class<?> , Integer > dueToBaseMap = new HashMap<>();

并在某处构建此地图

itemBaseMap.add( Canceled.class , 0 );
itemBaseMap.add( Modified.class , 1 );
itemBaseMap.add( Added.class , 2 );

dueToBaseMap.add( Provider.class, 0 );
dueToBaseMap.add( Company.class, 1 );

在 doSomething 方法中,您可以编写

void doSomething( ItemBase itemBase, DueToBase dueToBase ) {
    Integer itemBaseIndex = itemBaseMap.get( itemBase.getClass() );
    Integer dueToBaseIndex = dueToBaseMap.get( dueToBase.getClass() );

    Algorithm algorithm = algorithmTable[ itemBaseIndex, dueToBaseIndex ];

    algorithm.executeAlgorithm();
}
于 2014-06-04T11:24:33.283 回答