当前位置: 首页 > 知识库问答 >
问题:

如何在访问者模式中使用选中的异常

邢寒
2023-03-14

假设我有一套接受访问者(访问者模式)的类,但是由于这些类或特定访问者的性质,对它们执行工作可能会引发一个检查异常。

访客接受界面:

public interface Mammal
{
    void accept(MammalVisitor visitor);
}

访客界面:

public interface MammalVisitor
{
    void visit(Cat m);
    void visit(Dog m);
    void visit(Cow m);
}

以及哺乳动物的实现:

public class Cat implements Mammal
{
    public void accept(MammalVisitor visitor)
    {
        visitor.visit(this);
    }
}

我们假设是狗

现在假设我的访客是:

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");
    }
}

我将结果打印到标准输入输出:

Mammal m = MammalFactory.getMammal();
MammalPrinter mp = new MammalPrinter(System.out);
m.accept(mp);

然而,上面的句子在语法上是不正确的,因为它是可附加的。append(String)抛出java。伊奥。IOException。我不能声明每个访问方法的抛出,因为它没有在访问者界面中声明

我考虑过的解决方案:

  • Declare哺乳动物身上抛出IOException。accept(),这三个都是。visit(),以及所有三个打印机。visit()
  • 比上面的解决方案更好:Mammal和MammalVisitor现在与用法无关。然而,它们现在使用起来也很笨拙:没有抛出异常的访问者仍然被迫处理来自接受()方法的Throwable。

我还有另外两个解决方案,我更喜欢上面提到的,我会用它们来自我回复我的帖子。我想看看哪个更受社会大众的青睐。

共有3个答案

牧宁
2023-03-14

您缺少一个在内部处理IOException的选项。选项包括忽略、报告或将其包装为RuntimeException重新播放。。。。

// Ignore it (swallow it).
@Override 
public void visit(Cow m) {
    try {
        out.append("I'm a cow");
    } catch (IOException ioe) {
        // swallow this exception - it will never happen
    }
}

// report it
@Override 
public void visit(Cow m) {
    try {
        out.append("I'm a cow");
    } catch (IOException ioe) {
        ioe.printStackTrace();
    }
}

// wrap and rethrow it.
@Override 
public void visit(Cow m) {
    try {
        out.append("I'm a cow");
    } catch (IOException ioe) {
        throw new IllegalStateException("Unable to append to output", ioe);
    }
}
卫嘉谊
2023-03-14

您可以捕获检查过的异常,并将它们包装在未检查的异常中。例如,请参阅Spring如何将JDBC或JMS检查过的异常转换为未检查的异常。

孔城
2023-03-14

我本想提的是未经检查的包装重新投掷方法,但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;
}

和哺乳动物:

public interface Mammal
{
    <T extends Throwable> void accept(MammalVisitor<T> visitor) throws T;
}

以及哺乳动物的实施:

public class Cat implements Mammal
{
    @Override
    public <T extends Throwable> void accept(MammalVisitor<T> visitor) throws T
    {
        visitor.visit(this);
    }
}

狗和牛的实现是相同的。还有印刷访客:

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");
    }
}

和用法:

Mammal m = MammalFactory.getMammal();
MammalPrinter mp = new MammalPrinter(System.out);
try
{
    m.accept(mp);
}
catch (IOException e)
{
    System.err.println("An IOException occurred");
}

从最终用户的角度来看,这将带来更直观、更易于实现的使用。

使用这种模式,如果访问者没有要抛出的选中异常,他们会在实现中指定一些未选中的异常作为泛型:

public class MammalPrinter implements MammalVisitor<RuntimeException>
{

当哺乳动物。使用上述访问者调用accept(),不需要捕捉语法正确的内容。也许您可以通过创建一个名为“NeverThrown”的RuntimeException扩展来进一步提高可读性,它有一个私有构造函数。

 类似资料:
  • 我必须使用访问者设计模式编写一个应用程序,如(https://www.baeldung.com/java-visitor-pattern),一个示例元素如下所示: vistor界面看起来像下面的代码,我可能不会更改界面代码。 在Visitor(AbstractVisitor类)的实现中,如果hashtable子befehle中还没有调用类的id,我必须抛出一个“UndefinedSubroutin

  • 主要内容:介绍,实现,ComputerPart.java,Keyboard.java,Monitor.java,Mouse.java,Computer.java,ComputerPartVisitor.java,ComputerPartDisplayVisitor.java,VisitorPatternDemo.java在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行

  • 亦称: Visitor 意图 访问者模式是一种行为设计模式, 它能将算法与其所作用的对象隔离开来。 问题 假如你的团队开发了一款能够使用巨型图像中地理信息的应用程序。 图像中的每个节点既能代表复杂实体 (例如一座城市), 也能代表更精细的对象 (例如工业区和旅游景点等)。 如果节点代表的真实对象之间存在公路, 那么这些节点就会相互连接。 在程序内部, 每个节点的类型都由其所属的类来表示, 每个特定

  • 在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。 介绍 意图:主要将数据结构与数据操作分离。 主要解决:稳定的数据结构和易变的操作耦合问题。 何时使用:需要对一个对象结构中的对象进行

  • 简介 访问者模式是一种将算法与对象结构分离的软件设计模式。 这个模式的基本想法如下:首先我们拥有一个由许多对象构成的对象结构,这些对象的类都拥有一个accept方法用来接受访问者对象;访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作出不同的反应;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施accept方法,在每一个元素的accept方

  • 在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。 介绍 意图:主要将数据结构与数据操作分离。 主要解决:稳定的数据结构和易变的操作耦合问题。 何时使用:需要对一个对象结构中的对象进行