Gle*_*ane 16 java exception visitor
假设我有一套接受访问者(访问者模式)的类,但由于这些类或特定访问者的性质,执行它们可能会抛出一个已检查的异常.
访客接受界面:
public interface Mammal
{
void accept(MammalVisitor visitor);
}
Run Code Online (Sandbox Code Playgroud)
访客界面:
public interface MammalVisitor
{
void visit(Cat m);
void visit(Dog m);
void visit(Cow m);
}
Run Code Online (Sandbox Code Playgroud)
哺乳动物的实施:
public class Cat implements Mammal
{
public void accept(MammalVisitor visitor)
{
visitor.visit(this);
}
}
Run Code Online (Sandbox Code Playgroud)
我们假设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");
}
}
Run Code Online (Sandbox Code Playgroud)
然后我将结果打印到stdio:
Mammal m = MammalFactory.getMammal();
MammalPrinter mp = new MammalPrinter(System.out);
m.accept(mp);
Run Code Online (Sandbox Code Playgroud)
但是,上面的MammalPrinter在语法上是不正确的,因为Appendable.append(String)抛出java.io.IOException.我不能在每个访问方法上声明throw,因为它没有在访问者界面中声明.
我考虑过的解决方案:
throws IOException上Mammal.accept(),所有三个MammalVisitor.visit(),三个人MammalPrinter.visit()
throws Throwable上Mammal.accept(),并且所有三个MammalVisitor.visit(),并宣布throws IOException在所有三个MammalPrinter.visit()
我有两个其他解决方案,我赞成以上,我将自己回答我的帖子.我希望看到哪一个受到整个社区的青睐.
我要提到未经检查的包裹重新投掷方法,但Giodude打败了我.相反,我会建议另一种方法,我称之为礼貌例外(因为它作为礼貌实施者集成在界面中).
在设计访问者和哺乳动物界面时,我装备它们来处理用户选择的一个例外.访客:
public interface MammalVisitor<T extends Throwable>
{
void visit(Cat m) throws T;
void visit(Dog m) throws T;
void visit(Cow m) throws T;
}
Run Code Online (Sandbox Code Playgroud)
和哺乳动物:
public interface Mammal
{
<T extends Throwable> void accept(MammalVisitor<T> visitor) throws T;
}
Run Code Online (Sandbox Code Playgroud)
而哺乳动物的实施:
public class Cat implements Mammal
{
@Override
public <T extends Throwable> void accept(MammalVisitor<T> visitor) throws T
{
visitor.visit(this);
}
}
Run Code Online (Sandbox Code Playgroud)
狗和牛的实施方式完全相同.和印刷访客:
public class MammalPrinter implements MammalVisitor<IOException>
{
private final Appendable out;
public MammalPrinter(Appendable out)
{
this.out = out;
}
@Override
public void visit(Cat m) throws IOException
{
out.append("I'm a cat");
}
@Override
public void visit(Dog m) throws IOException
{
out.append("I'm a dog");
}
@Override
public void visit(Cow m) throws IOException
{
out.append("I'm a cow");
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
Mammal m = MammalFactory.getMammal();
MammalPrinter mp = new MammalPrinter(System.out);
try
{
m.accept(mp);
}
catch (IOException e)
{
System.err.println("An IOException occurred");
}
Run Code Online (Sandbox Code Playgroud)
从最终用户的角度来看,这使得使用起来更直观,更容易实现.
使用此模式,如果访问者没有要抛出的已检查异常,则会在其实现中指定一些未经检查的异常作为通用:
public class MammalPrinter implements MammalVisitor<RuntimeException>
{
Run Code Online (Sandbox Code Playgroud)
当使用上面的访问者调用Mammal.accept()时,不需要捕获语法正确.也许你可以通过对具有私有构造函数的名为"NeverThrown"的RuntimeException进行扩展来进一步提高可读性.