我正在帮助开发的程序应该输出几个动态生成的问题供用户回答。问题具有不同的类型,并且具有相应的类Constraint
,它们用用户给定的信息填充。我的问题是如何为不同的约束创建统一的行为。
---->Constraint<--------------------
| | |
FConstraint PConstraint TConstraint
| |
UConstraint AConstraint
基类Constraint
为空,TConstraint也是如此。
UConstraint
,PConstraint
和AConstraint
共享三个变量。但是,UConstraint
和AConstraint
还有一个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.
这个设计有比抽象函数更好的解决方案吗?
答案 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
的抽象类,它应具有共享变量。 UConstraint
,AConstraint
应该扩展这个具有共享变量的抽象类。其余类可以直接实现Constraint
接口。代码实例应该像
Constraint constraint = item.getConstraint();
constraint.doWork(..);
总是更好的设计是针对接口编写代码