假设我有一套接受访问者的类(访问者模式),但由于这些类或特定访问者的性质,对它们执行工作可能会引发检查异常。
访客接受界面:
public interface Mammal
{
void accept(MammalVisitor visitor);
}
访客界面:
public interface MammalVisitor
{
void visit(Cat m);
void visit(Dog m);
void visit(Cow m);
}
以及 Mammal 的实现:
public class Cat implements Mammal
{
public void accept(MammalVisitor visitor)
{
visitor.visit(this);
}
}
我们假设 Dog & Cow 的实现与 Cat 相同
现在假设我的访客是:
public class MammalPrinter implements MammalVisitor
{
private final Appendable out;
public MammalPrinter(Appendable out)
{
this.out = out;
}
@Override
public void visit(Cat m)
{
out.append("I'm a cat");
}
@Override
public void visit(Dog m)
{
out.append("I'm a dog");
}
@Override
public void visit(Cow m)
{
out.append("I'm a cow");
}
}
我将结果打印到 stdio:
Mammal m = MammalFactory.getMammal();
MammalPrinter mp = new MammalPrinter(System.out);
m.accept(mp);
但是,上面的 MammalPrinter 在语法上是不正确的,因为 Appendable.append(String) throws java.io.IOException
。我不能在每个访问方法上声明 throw,因为它没有在访问者界面中声明。
我考虑过的解决方案:
- 声明
throws IOException
,Mammal.accept()
所有三个MammalVisitor.visit()
,所有三个MammalPrinter.visit()
- 非常令人讨厌:Mammal 和 MammalVisitor 接口现在意识到它们涉及 IO 的潜在用途,这与使用访问者模式的全部意义背道而驰。
- 声明所有三个
throws Throwable
,并声明所有三个Mammal.accept()
MammalVisitor.visit()
throws IOException
MammalPrinter.visit()
- 比上述解决方案更好: Mammal 和 MammalVisitor 现在使用不可知论。但是,它们现在也很难使用:不抛出异常的访问者仍然被迫从 accept() 方法处理 Throwable。
我有两个比上述更喜欢的解决方案,我将用它们自行回答我的帖子。我想看看哪一个受到整个社区的青睐。