隐藏字段时如何避免instanceof

时间:2019-05-17 14:01:31

标签: oop inheritance design-patterns

我首先要说我已经阅读了很多有关避免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来实际检索持续时间并进行所需的调度。

一个想法是,可以将决定某个特定时间类型意味着什么的努力转移到策略本身中。感觉它也应该只是基于名称,但这需要相当大地更改一些调度代码,并最终破坏了仅在开发这些调度中开发的一些范例。也许这是我们需要的解决方案,但感觉它不应该是唯一的解决方案。

就设计模式而言,是否有一种更好的方法不会导致代码气味的实例,从而使调用者可以根据这些字段来决定要做什么?

1 个答案:

答案 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
  }
}