java 中的访客模式示例
Visitor
模式允许你向一组类添加新操作或方法,而无需修改这些类的结构。
当你想要在对象上集中特定操作而不扩展对象或不修改对象时,此模式特别有用。
来自维基百科的 UML 图:
代码段:
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);
}
}
}
说明:
Visitable
(Element
)是一个接口,这个接口方法必须添加到一组类中。Visitor
是一个接口,它包含对Visitable
元素执行操作的方法。GameVisitor
是一个类,它实现了Visitor
接口(ConcreteVisitor
)。- 每个
Visitable
元素接受Visitor
并调用Visitor
接口的相关方法。 - 你可以将
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
用例/适用性:
- 必须对分组在结构中的不同类型的对象执行类似的操作
- 你需要执行许多不同且不相关的操作。它将操作与对象结构分开
- 必须添加新操作而不改变对象结构
- *将相关操作收集到单个类中,*而不是强制你更改或派生类
- 将函数添加到你没有源或无法更改源的类库 **
其他参考: