java 中的访客模式示例

Visitor 模式允许你向一组类添加新操作或方法,而无需修改这些类的结构。

当你想要在对象上集中特定操作而不扩展对象或不修改对象时,此模式特别有用。

来自维基百科的 UML 图:

StackOverflow 文档

代码段:

import java.util.HashMap;

interface Visitable{
    void accept(Visitor visitor);
}

interface Visitor{
    void logGameStatistics(Chess chess);
    void logGameStatistics(Checkers checkers);
    void logGameStatistics(Ludo ludo);    
}
class GameVisitor implements Visitor{
    public void logGameStatistics(Chess chess){
        System.out.println("Logging Chess statistics: Game Completion duration, number of moves etc..");    
    }
    public void logGameStatistics(Checkers checkers){
        System.out.println("Logging Checkers statistics: Game Completion duration, remaining coins of loser");    
    }
    public void logGameStatistics(Ludo ludo){
        System.out.println("Logging Ludo statistics: Game Completion duration, remaining coins of loser");    
    }
}

abstract class Game{
    // Add game related attributes and methods here
    public Game(){
    
    }
    public void getNextMove(){};
    public void makeNextMove(){}
    public abstract String getName();
}
class Chess extends Game implements Visitable{
    public String getName(){
        return Chess.class.getName();
    }
    public void accept(Visitor visitor){
        visitor.logGameStatistics(this);
    }
}
class Checkers extends Game implements Visitable{
    public String getName(){
        return Checkers.class.getName();
    }
    public void accept(Visitor visitor){
        visitor.logGameStatistics(this);
    }
}
class Ludo extends Game implements Visitable{
    public String getName(){
        return Ludo.class.getName();
    }
    public void accept(Visitor visitor){
        visitor.logGameStatistics(this);
    }
}

public class VisitorPattern{
    public static void main(String args[]){
        Visitor visitor = new GameVisitor();
        Visitable games[] = { new Chess(),new Checkers(), new Ludo()};
        for (Visitable v : games){
            v.accept(visitor);
        }
    }
}

说明:

  1. VisitableElement)是一个接口,这个接口方法必须添加到一组类中。
  2. Visitor 是一个接口,它包含对 Visitable 元素执行操作的方法。
  3. GameVisitor 是一个类,它实现了 Visitor 接口(ConcreteVisitor)。
  4. 每个 Visitable 元素接受 Visitor 并调用 Visitor 接口的相关方法。
  5. 你可以将 Game 视为 Element,将具体游戏如 Chess,Checkers and Ludo 视为 ConcreteElements

在上面的例子中,Chess, Checkers and Ludo 是三种不同的游戏(和 Visitable 类)。在一个晴朗的日子里,我遇到了记录每个游戏统计数据的场景。因此,如果不修改单个类来实现统计功能,你可以将该职责集中在 GameVisitor 类中,这样可以在不修改每个游戏结构的情况下为你提供帮助。

输出:

Logging Chess statistics: Game Completion duration, number of moves etc..
Logging Checkers statistics: Game Completion duration, remaining coins of loser
Logging Ludo statistics: Game Completion duration, remaining coins of loser

用例/适用性:

  1. 必须对分组在结构中的不同类型的对象执行类似的操作
  2. 你需要执行许多不同且不相关的操作。它将操作与对象结构分开
  3. 必须添加新操作而不改变对象结构
  4. *将相关操作收集到单个类中,*而不是强制你更改或派生类
  5. 将函数添加到你没有源或无法更改源的类库 **

其他参考:

oodesign

sourcemaking