如何为抽象类或接口的子类型实现Visitor模式?

时间:2019-03-03 12:15:08

标签: java oop design-patterns solid-principles visitor

我遇到了这个特定问题,无法解决其他问题。 我正在尝试为游戏实现“访客”,访客是Attack类,它必须在矩阵中搜索可能包含Characters的单元格,如果角色是敌人而不是敌人一个朋友,破坏它。

我遇到的麻烦是没有使用InstanceOf来访问角色,因为它破坏了开放封闭原则。 这是我的代码:

访问者界面

public interface Visitor {
    public void visit(GroundCell c);
    public void visit(MountainCell c);
    public void visit(BuildingCell c);
    public void visit(WaterCell c);
    public void visit(Foe f);
    public void visit(Friend f);}

攻击抽象类

public abstract class Attack implements Visitor {

}

攻击具体课程

public class TankAttack extends Attack{

...

@Override
public void visit(GroundCell c) {
    //here, i'd like to call  c.getCharacter.accept(this) 
}

但是我收到一个错误消息,当我仅对其子类需要它时,应该首先实现Visit(Character c)。

在TankAttack类中我该怎么做以访问Character的Friend或Foe子类,并且不使用InstanceOf破坏设计?

为澄清起见进行编辑:Friend和Foe是Character的子类。

2 个答案:

答案 0 :(得分:0)

访客无法以这种方式工作。

这里声明为参数的所有类都是已访问的类:

function x(input){
    if (input.observable) input = input.observable;
    if (input.raw) input = input.raw
}

所有这些都必须定义一个public void visit(GroundCell c); public void visit(MountainCell c); public void visit(BuildingCell c); public void visit(WaterCell c); public void visit(Foe f); public void visit(Friend f);} 方法,其意思是“我接受访问者的访问”。
在它们内部,我们调用:accept(Visitor visitor)来以预期的过载(两次调度)有效地执行访问。

通过这种方式,您可以编写:

visitor.visit(this)

或更笼统地说,您公开以访客的基本类型为参数的方法,例如:

Attack attack = new TankAttack(); // visitor
Visited visitedOne = new GroundCell(); // visited one
Visited visitedTwo = new MountainCell(); // visited two

// accept the visitor and perform the double dispatch to invoke the specific method
visitedOne.accept(attack); 
visitedTwo.accept(attack); 

并使用它:

public void attack(Visited visited, Attack attack){
     visited.accept(attack); // no need instance of
}

答案 1 :(得分:0)

我几个小时后解决了。此问题不是由Visitor模式的错误实现引起的,而是因为超类被称为Character,就像java.lang.Character一样。在编程Java游戏时要小心不要覆盖此类。