如何整合多个类并避免使用instanceof?

时间:2012-05-23 18:10:58

标签: java

我正在帮助开发的程序应该输出几个动态生成的问题供用户回答。问题具有不同的类型,并且具有相应的类Constraint,它们用用户给定的信息填充。我的问题是如何为不同的约束创建统一的行为。

                    ---->Constraint<--------------------
                    |                  |               |
                  FConstraint        PConstraint    TConstraint
                  |         |
            UConstraint AConstraint

基类Constraint为空,TConstraint也是如此。

UConstraintPConstraintAConstraint共享三个变量。但是,UConstraintAConstraint还有一个PConstraint没有的额外变量。

我觉得我正试图用一些钳子敲打砖墙。我的想法是使用签名为Constraint提供一个抽象方法:

// All answers are of type string.
abstract void setValue(string variable, string answer);

每个Constraint子类都实现了这些。但是,传递一个字符串来确定要设置哪个变量似乎容易出错,同样也有类似的恶臭。

第二个选项是将三个相似的变量移动到Constraint中,但仍然会留下UConstraint, AConstraint我可能需要设置的额外信息。 TConstraint不需要任何这些内容,这没有任何帮助。

我当前的蛮力“搞这个设计。”解决方案是instanceof汤,我在其中检查并填写缺少的特定于约束的信息。

Object constraint = item.getConstraint();

if (constraint instanceof AConstraint) {
    AConstraint constraint = (AConstraint) constraint;

    if (constraint.getValue() == null) {
        constraint.setValue(string);
    } else if (constraint.getKey() == null) {
        constraint.setKey(string);
    } // More of the same.
} else if (constraint instanceof PConstraint) {
    // As the above if() group.
} // etc.

这个设计有比抽象函数更好的解决方案吗?

5 个答案:

答案 0 :(得分:3)

使用此原则

在接口中编程,并封装在抽象类或接口中不断变化的行为。

例如:对于上面给出的例子

接口 - 约束

抽象类 - FConstraint

具体类 - PConstraint,TConstraint,UConstraint,AConstraint

答案 1 :(得分:3)

您的问题没有足够的信息来说明您在每种情况下需要做的实际工作,但通常是这样的代码:

Object constraint = item.getConstraint();

if (constraint instanceof AConstraint) {
    // Work
} else if (constraint instanceof PConstraint) {
    // Work
} // etc.

是一种强烈的气味,使用polymorphism并重构成这样的东西:

Constraint constraint = item.getConstraint();
constraint.doWork(...);

特定类看起来像这样:

public class AConstraint {
  public ... doWork(...) {
    if (getValue() == null) {
      setValue(string);
    } else if (getKey() == null) {
      setKey(string);
    } // More of the same.      
  }
}

答案 2 :(得分:2)

你可以这样做:

public interface Constraint{}

public abstract class VariableConstraint implements Constraint 
{ 
  /* hold 3 shared variables here */
}

public class UConstraint extends VariableConstraint{}
public class PConstraint extends VariableConstraint{}
public class AConstraint extends VariableConstraint{}

public abstract class EmptyConstraint implements Constraint {}

public class TConstraint extends EmptyConstraint {}

答案 3 :(得分:1)

Constraint中指定常用功能:您希望能够在Constraint对象上执行的任何操作(实际上可能是其中一个子类型的对象),您有一个您在子类中重写的Constraint中该功能的方法。

对于那些功能没有意义的父类,你可以有一些简单的(例如空的)实现。

这样你就不需要关心对象的具体类了,只需使用超类提供的工具

答案 4 :(得分:1)

Constraint作为接口。定义一个扩展此Constraint的抽象类,它应具有共享变量。 UConstraintAConstraint应该扩展这个具有共享变量的抽象类。其余类可以直接实现Constraint接口。代码实例应该像

一样改变
Constraint constraint = item.getConstraint();
constraint.doWork(..);

总是更好的设计是针对接口编写代码