访客设计模式意图:误导或我遗失了什么?

时间:2014-05-31 09:36:51

标签: java design-patterns extensibility visitor

参考书"可重复使用的面向对象软件的设计模式元素&#34>;在四人帮中,访客模式的意图解释如下:

  

表示要对对象结构的元素执行的操作。访问者允许您定义新操作,而无需更改其操作的元素的类。

我读到的关于访客模式的另一个优点是:

  

添加新操作没有源代码的课程..

我在Google上进行了深入搜索,但我没有找到任何显示如何执行此操作的示例。 所以让我们举一个简单的例子:

public interface MyInterface {
    public void myMethod();
}

public class MyClassA implements MyInterface {

    /* (non-Javadoc)
     * @see com.mycomp.tutorials.designpattern.behavorials.MyInterface#myMethodA()
     */
    public void myMethod() {
        System.out.println("myMethodA implemented in MyClassA");

    }

}

public class MyClassB implements MyInterface {

    /* (non-Javadoc)
     * @see com.mycomp.tutorials.designpattern.behavorials.MyInterface#myMethodA()
     */
    public void myMethod() {
        System.out.println("myMethod implemented in MyClassB");

    }

}

那么如何使用访问者模式将新方法myNewMethod()添加到此类层次结构而不更改它们?

4 个答案:

答案 0 :(得分:2)

您的示例是访问者模式。它只是继承。

访问者模式首先需要访问者interface

interface ThingVisitor {
    void visit(ThingA a);
    void visit(ThingB b);
}

现在需要interface Thing

interface Thing {
    void accept(ThingVisitor visitor);
}

例如,ThingA的实施将是

class ThingA implements Thing {
    public void accept(final ThingVisitor visitor) {
        visitor.visit(this);
    }
}

现在您看到处理Thing类型的逻辑包含在ThingVisitor的实现中。

答案 1 :(得分:0)

访问者模式假定您在要学习的课程中有一个方法"访问"它接受并执行访问者,这里是example。该模式不是通过向外部类添加功能而是为了本地化访问者中的功能而激励的,否则这些功能将分布在几个类上,例如,用于保存元素(参见示例)。

答案 2 :(得分:0)

我们假设您有一个Message类,以及2个子类Email和Sms。

您可以对这两个类进行许多操作,例如sendToOnePerson()sendToSeveralPeople()。但您可能不希望直接在Email和Sms类中使用这些方法,因为它将它们紧密地耦合到SMTP /电话系统。并且您还希望能够在futre中添加其他操作,例如forward()或delete()等等。所以你可以使用的第一个实现是

public void delete(Message message) {
    if (message instanceof Email) {
        deleteEmail(Email) message);
    }
    else if (message instanceof Sms) {
        deleteSms((Sms) message);
    }
}

但这很难看:它不是面向对象的,如果出现新的VoiceMessage子类,它将会失败。

另一种方法是使用访客模式。

public interface MessageVisitor {
    void visitEmail(Email email);
    void visitSms(Sms sms);
}

public abstract class Message {
    public void accept(MessageVisitor visitor);
}

public class Email extends Message {
    @Override
    public void accept(MessageVisitor visitor) {
        visitor.visitEmail(this);
    }
}

public class Sms extends Message {
    @Override
    public void accept(MessageVisitor visitor) {
        visitor.visitSms(this);
    }
}

这样,要实现send(),您只需要一个可以发送电子邮件并发送短信的MessageVisitor实现:

SendMessageVisitor visitor = new SendMessageVisitor();
message.accept(visitor);

如果你引入一个新的delete()操作,你根本不必触及Message类。您只需要一个DeleteMessageVisitor:

DeleteMessageVisitor visitor = new DeleteMessageVisitor();
message.accept(visitor);

因此,基本上,如果您通过不实际修改Message类而向Message类添加了多态方法,那就有点像。

答案 3 :(得分:0)

访客模式的快速说明。

需要修改的类必须全部实现' accept'方法。客户端调用此accept方法对该类系列执行一些新操作,从而扩展其功能。通过为每个特定操作传入不同的访问者类,客户端可以使用这一种接受方法来执行各种新操作。访问者类包含多个重写的访问方法,这些方法定义了如何为系列中的每个类实现相同的特定操作。这些访问方法传递了一个可以工作的实例