我首先要说我已经阅读了很多有关避免instanceof的问题,但是我看不到任何与我们所看到的内容完全相符的问题。不过,请告诉我您是否确实能解决这个特定问题!
我们现在面临的一个问题是,我们有一个类负责保存有关在特定时间要采取的措施的信息。这些时间可以是单个操作,也可以是一段时间内重复发生。我们有一个字段(动作持续时间)仅对重复动作有效。最初,我们将时间类型设为Enum,将持续时间设为单独字段作为单个类的一部分。
class Action {
long duration;
Enum timeType;
}
更改为:
class Action {
TimeTypeStrategy timeTypeStrategy;
}
class RecurringTimeTypeStrategy extends TimeTypeStrategy {
long duration
}
class SingleTimeTypeStrategy extend TimeTypeStrategy {
}
abstract class TimeTypeStrategy {
}
因此,使用此修改后的代码,我们基本上可以说我们甚至只能拥有一种类型,而持续时间只能是重复时间类型的属性。但是,这也意味着,每当我们要根据其重复时间类型采取行动(或使用行动的其他类)来处理它时,都需要在timeTypeStrategy字段上调用instanceof来实际检索持续时间并进行所需的调度。
一个想法是,可以将决定某个特定时间类型意味着什么的努力转移到策略本身中。感觉它也应该只是基于名称,但这需要相当大地更改一些调度代码,并最终破坏了仅在开发这些调度中开发的一些范例。也许这是我们需要的解决方案,但感觉它不应该是唯一的解决方案。
就设计模式而言,是否有一种更好的方法不会导致代码气味的实例,从而使调用者可以根据这些字段来决定要做什么?
答案 0 :(得分:1)
我认为您正在寻找的是访客设计模式。您可以具有以下类层次结构:
abstract class Action {
Enum timeType;
abstract void Accept(IVisitor visitor);
}
class SingleAction extends Action {
override void Accept(IVisitor visitor) {
visitor.Visit(this);
}
}
class RepeatedAction extends Action {
long duration;
override void Accept(IVisitor visitor) {
visitor.Visit(this);
}
}
那么您可以拥有一个访问者界面:
interface IVisitor {
void Visit(SingleAction action);
void Visit(RepeatedAction action);
}
和访问者实现:
class ActionVisitor implements IVisitor {
void Visit(SingleAction action) {
// Execute the action
}
void Visit(RepeatedAction action) {
// Here you can access action.duration and schedule the action
}
}