`

Design Pattern: Visitor 模式

 
阅读更多

在Java中所有的物件都继承自Object物件,这样作的优点之一,就是使得一些集合物件的资料结构容易管理,例如您可以将任何型态的物件放入Vector中。

然而现在有个问题是,如果您的集合(connection)物件中不仅储存一种型态的物件,如果想要对这些物件作出一些个别化的操作,首要条件就是要知道该物件的型态,使用 instanceof 似乎是个不错的方式,在程式简单的情况下,也许您会这么作:

 public class ElementA {
    // some implementing
 }
 
 public class ElementB {
    // some implementing
 }

 public class ElementC {
    // some implementing
 }

 // ......

    Iterator iterator = arrayList.iterator()
    while (iterator.hasNext()) {
        if (o instanceof ElementA)
        (ElementA) o.operationA();
        else if (o instanceof ElementB)
         (ElementB) o.operationB();
      else if (o instanceof ElementC)
         (ElementC) o.operationC();
      else
         System.out.println(
                  "Sorry! I don't know who you are! "
                   + o.toString());
        //....
    }

    //....

 
这么作并不是不可以,只是将来的扩充性不大,如果今天您想要一次改变对每一种类型物件的操作,您必须修改很多地方。

从物件自身的角度来想好了,物件在一个个的房子中,物件说:“不要在房子外费尽心思判断了,即然您不知道我是谁,那么您就进来访问我好了,我告诉您我是谁,这么一来您就知道如何操作我了!”

用程式来实现上面这个描述:

  • IElement.java
public interface IElement { 
    public void accept(IVisitor visitor); 
} 

 

  • ElementA.java
public class ElementA implements IElement { 
    public void accept(IVisitor visitor) { 
        visitor.visit(this); 
    }

    public void operationA() { 
        System.out.println(
              "do A's job....such-and-such...."); 
    } 
} 

 

  • ElementB.java
public class ElementB implements IElement { 
    public void accept(IVisitor visitor) { 
        visitor.visit(this); 
    }

    public void operationB() { 
        System.out.println(
           "do B's job....such-and-such...."); 
    }
} 

 

  • ElementC.java
public class ElementC implements IElement { 
    public void accept(IVisitor visitor) { 
        visitor.visit(this); 
    }

    public void operationC() { 
        System.out.println(
            "do C's job....such-and-such...."); 
    } 
} 

 

  • IVisitor.java
public interface IVisitor { 
    public void visit(ElementA element); 
    public void visit(ElementB element); 
    public void visit(ElementC element); 
}  

 

  • VisitorA.java
public class VisitorA implements IVisitor { 
    public void visit(ElementA element) { 
        element.operationA(); 
    }

    public void visit(ElementB element) { 
        element.operationB(); 
    }

    public void visit(ElementC element) { 
        element.operationC(); 
    } 
}  

 

  • Main.java
public class Main { 
    public static void main(String[] args) { 
        // know nothing about their type 
        // after storing them into Element array 
        IElement[] list = {new ElementA(), 
                           new ElementB(), 
                           new ElementC()}; 

        IVisitor visitor = new VisitorA();

        for (int i=0; i < list.length; i++) 
            list[i].accept(visitor); 
    } 
} 


Visitor访问是基于overload来完成,对于每一个实现IElement的物件来说,它接受IVisitor来访问它,在accept()方法中,IVisitor使用正确的方法来访问IElement(显然的,这么部份可以靠不同的函式名称,或是overload来达成),并在visit() 中对IElement作出对应的操作,如果您今天想要换掉每一个IElement的操作,只要更换IVisitor类型的物件就可以了,也就是这行:

 // IVisitor visitor = new VisitorA();
 // 换掉一个IVisitor,就可以换掉所有的操作
 // 不用修改多个地方
 IVisitor visitor = new VisitorB();

 

举个实际的例子,假设VisitorA只是个懒惰的推销员好了,今天有一个比较勤快的推销员VisitorB,在访问过IElement之后,会对 IElement作出更多的操作,要在程式中实现VisitorB,只要增加一个VisitorB类别就可以了:

  • VisitorB.java
public class VisitorB implements IVisitor { 
    public void visit(ElementA element) { 
        System.out.println("VisitorB is a hard worker...."); 
        element.operationA(); 
        System.out.println(
            "I want to do some extra work on A...."); 
    }

    public void visit(ElementB element) { 
        System.out.println("VisitorB is a hard worker...."); 
        element.operationB(); 
        System.out.println(
                   "I want to do some extra work on B...."); 
    }

    public void visit(ElementC element) { 
        System.out.println("VisitorB is a hard worker...."); 
        element.operationC(); 
        System.out.println(
                  "I want to do some extra work on C...."); 
    } 
} 


改一下Main来示范:

  • Main.java
public class Main { 
    public static void main(String[] args) { 
        IElement[] list = {new ElementA(), 
                           new ElementB(), 
                           new ElementC()}; 

        System.out.println("visitorA is coming......."); 
        IVisitor visitorA = new VisitorA(); 
        for (int i=0; i < list.length; i++) 
           list[i].accept(visitorA);

        System.out.println("\nvisitorB is coming......."); 
        IVisitor visitorB = new VisitorB(); 
        for (int i=0; i < list.length; i++) 
            list[i].accept(visitorB); 
    } 
} 


在范例中的System.out.println();只是个示意,它也可能是您对IElement的额外方法的直接调用。

Java World中有一篇文章,提到可以利用reflection来改进使用访问者模式时的弹性,有兴趣的可以进一步参考一下Reflect on the Visitor design pattern

分享到:
评论

相关推荐

    DesignPattern:设计模式

    DesignPattern-master这个压缩包可能包含了一个关于设计模式的项目或者教程资源。 设计模式分为三类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)和行为型模式(Behavioral Patterns)...

    designPattern:设计模式相关代码实现

    "designPattern:设计模式相关代码实现"这个项目,显然提供了不同设计模式在Java语言中的实际应用示例。 在Java世界里,设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。每种模式都针对特定的编程问题...

    DesignPattern:设计模式演示程序

    这个名为"DesignPattern"的压缩包文件很可能包含了一个Java实现的各种设计模式的示例程序。 在这个"DesignPattern-master"目录中,我们可以期待找到一系列与设计模式相关的Java源代码文件(.java),每个文件或...

    C++设计模式(Design Pattern)范例源代码

    23种设计模式(Design Pattern)的C++实现范例,包括下面列出的各种模式,代码包含较详细注释。另外附上“设计模式迷你手册.chm”供参考。 注:项目在 VS2008 下使用。 创建型: 抽象工厂模式(Abstract Factory) 生成...

    DesignPattern:C#设计模式示例

    "DesignPattern:C#设计模式示例"这个资源很可能是包含多个C#实现的设计模式示例代码库。 设计模式通常分为三类:创建型、结构型和行为型。每种模式都解决了特定场景下的问题,并提供了良好的代码组织和扩展性。 ...

    DesignPattern:设计模式的学习笔记和示例代码

    设计模式是软件工程中的一种最佳实践,它是在特定情境下解决常见问题的经验总结。...在DesignPattern-master这个压缩包中,你可以找到关于这些模式的详细讲解和实例代码,为你的Java开发之旅提供宝贵的参考资料。

    Design-pattern:设计模式

    这个名为"Design-pattern:设计模式"的压缩包可能包含了一个关于设计模式的学习资源,比如代码示例或者教程。 创建型设计模式是设计模式中的一个类别,主要关注对象的创建过程。这类模式包括工厂方法(Factory ...

    JAVA 23种设计模式(全).Design Pattern_Java模式

    包括策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、访问者模式(Visitor)、责任链模式(Chain of Responsibility)、命令模式(Command)、备忘录模式...

    designpattern:PHP设计模式教程

    本教程的"designpattern-master"可能包含以上各种设计模式的实例代码和详细解释,帮助学习者通过实践掌握这些模式。在实际项目中,灵活运用这些设计模式可以提高代码质量,使项目更加健壮和易于维护。对于PHP开发者...

    Design Pattern(设计模式)讲义

    ### Design Pattern(设计模式)讲义 #### 一、引言 设计模式是软件工程领域的一个重要主题,它提供了一套解决常见问题的方案。侯捷老师的讲义为我们揭示了设计模式背后的原理与实践方法。这份讲义不仅包含了GoF...

    design pattern PPT

    设计模式(Design Pattern)是软件工程中用于解决软件设计问题的既定方案。设计模式并非直接的代码实现,而是一套被验证过的通用解决方案模板。它们是由经验丰富的软件开发者总结出的,在特定上下文中对常见问题的...

    Design Pattern英文版

    设计模式(Design Pattern)是软件工程中的一种经验总结,它是在特定上下文中为解决常见问题而提出的一套可复用的解决方案。设计模式并不直接实现为代码,而是提供了一种在面向对象设计中如何处理常见问题的指南。...

    design pattern设计模式范例

    本资料库中的"design pattern设计模式范例"提供了23种经典设计模式以及最新的范式用法,非常适合用于项目重构或作为学习设计模式的参考。 首先,我们来看23种经典的设计模式,它们通常分为三类:创建型、结构型和...

    阅读java源码-JavaDesignPattern:23种设计模式Java实现

    在“阅读java源码-JavaDesignPattern:23种设计模式Java实现”中,我们将深入探讨这23种设计模式的Java实现。 1. **创建型模式**(Creational Patterns): - **单例模式(Singleton)**:确保一个类只有一个实例,...

    Head First Design Pattern

    3. 行为型设计模式:例如策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、命令模式(Command)、迭代器模式(Iterator)、访问者模式(Visitor)、备忘录模式(Memento)、状态...

    design-pattern:标准设计模式的实施

    本资源"design-pattern:标准设计模式的实施"很可能是关于如何在Java中应用经典设计模式的详细指南。 设计模式分为三大类:创建型模式、结构型模式和行为型模式。每种模式都有其特定的目的和应用场景。 1. 创建型...

    Java-DesignPattern:Java中23种常见的设计模式

    本资料包“Java-DesignPattern:Java中23种常见的设计模式”涵盖了软件设计中的重要概念,以下是这些模式的详细说明: 1. **单例模式(Singleton)**:确保一个类只有一个实例,并提供全局访问点。防止其他对象多次...

    designpattern.zip

    本资源"designpattern.zip"包含了对Java中23种经典设计模式的详细讲解和代码实例,对于中高级Java工程师来说,是提升开发技能的必备学习材料。 设计模式通常分为创建型、结构型和行为型三大类。创建型设计模式关注...

Global site tag (gtag.js) - Google Analytics