4

我有以下类图(访问者模式实现):

在此处输入图像描述

预期结果:
1) WiredVisitor 应该只访问 Router 和 WiredNetworkCard
2) WirelessVisitor 应该只访问 Router 和 WirelessNetworkCard

所以,我的问题是:我应该如何更改设计(或代码)以实现我的预期结果?

PS我目前的解决方案是在两个访问者的每个访问(卡片:INetworkCard)方法中添加以下代码:

// in WiredVisitor
if (card.getClass.equals(WiredNetworkCard.class)){
    // do logic of visit method
}

// in WirelessVisitor
if (card.getClass.equals(WirelessNetworkCard.class)){
    // do logic of visit method
}
4

4 回答 4

3

本着非循环访问者模式的精神,将访问者分成子类特定的访问者。请注意,您仍然需要类型检查,但它包含在被访问的类型中:

以下是访问者界面:

interface IVisitor {
}

interface IRouterVisitor extends IVisitor {
  void visit(Router router);
}

interface INetworkCardVisitor extends IVisitor {
}

interface IWirelessNetworkCardVisitor extends INetworkCardVisitor {
  void visit(WirelessNetworkCard card);
}

interface IWiredNetworkCardVisitor extends INetworkCardVisitor {
  void visit(WiredNetworkCard card);
}

具体的访问者将如下所示:

class WiredVisitor implements IWiredNetworkCardVisitor, IRouterVisitor  {
  // ...
}

class WirelessVisitor implements IWirelessNetworkCardVisitor, IRouterVisitor {
  // ...
}

和访问的对象:

interface INetworkElement {
  void accept(IVisitor visitor);
}

class Router implements INetworkElement {
  @Override
  public void accept(IVisitor visitor) {
    if (visitor instanceof IRouterVisitor) {
      ((IRouterVisitor)visitor).visit(this);
    }
  }
}

interface INetworkCard extends INetworkElement {}

class WiredNetworkCard implements INetworkCard {
  @Override
  public void accept(IVisitor visitor) {
    if (visitor instanceof IWiredNetworkCardVisitor) {
      ((IWiredNetworkCardVisitor)visitor).visit(this);
    }
  }
}

class WirelessNetworkCard implements INetworkCard {
  @Override
  public void accept(IVisitor visitor) {
    if (visitor instanceof IWirelessNetworkCardVisitor) {
      ((IWirelessNetworkCardVisitor)visitor).visit(this);
    }
  }
}

在这些类型检查中,如果类型不是预期的类型,您也可以抛出错误,这取决于您希望在这种情况下发生什么。

于 2012-07-11T17:14:00.330 回答
0

例如,您可以这样做:

public interface IVisitor<T extends INetworkCard> {
   public void visit( T card );
}

然后您将访问者定义为:

public class WiredVisitor implements IVisitor<WiredNetworkCard> {
...
}


public class WirelessVisitor implements IVisitor<WirelessNetworkCard> {
...
}

这可能不是教科书的解决方案,但它非常干净且可读性强。

于 2012-07-10T23:00:06.357 回答
0

我认为这里的问题不在于访问者,而是当客户端通过传递一个错误来调用接受时。然后应该通过在那个时间点引发异常来处理它。WiredNetworkCardWirelessVisitor

但是所有这一切都发生在运行时,biziclop 的解决方案本身在编译时处理它。但我不喜欢 biziclop 的解决方案的地方在于,WiredVisitor它实现的方法也IVisitor<WiredNetworkCard>visit(router:Router)WiredNetworkCard

于 2012-07-11T06:31:40.123 回答
0

您可以只定义一些接口并在您希望它访问的每组元素上打一个...这样做的好处是:

  • 它是类型安全的
  • 没有运行时检查(因为不需要它们);没有运行时异常

这是我为您的示例所谈论的内容的实现:

  • 访客:

    interface  Wired {
        <R> R accept(Visitor<R> v);
    
        interface Visitor<R> {
            R visit(Router router);
    
            R visit(WiredNetworkCard wiredNetworkCard);
        }
    }
    
    interface Wireless {
        <R> R accept(Visitor<R> v);
    
        interface Visitor<R> {
            R visit(Router router);
    
            R visit(WirelessNetworkCard wirelessNetworkCard);
        }
    }
    
  • 要素:

    class Router implements Wired, Wireless {
        @Override
        public <R> R accept(Wired.Visitor<R> v) {
            return v.visit(this);
        }
    
        @Override
        public <R> R accept(Wireless.Visitor<R> v) {
            return v.visit(this);
        }
    }
    
    class WiredNetworkCard implements Wired {
        @Override
        public <R> R accept(Wired.Visitor<R> v) {
            return v.visit(this);
        }
    }
    
    class WirelessNetworkCard implements Wireless {
        @Override
        public <R> R accept(Wireless.Visitor<R> v) {
            return v.visit(this);
        }
    }
    
于 2018-06-27T21:09:40.273 回答