java设计模式之访问者(三)-经典访问者
上一讲描述了耦合在节点内部的访问者,访问逻辑放在每个节点之中,不方便维护和修改
今天我们描述经典的访问者模式
UML图如下
简单描述下,要实现一个家谱类Genealogy的遍历,家谱包含所有家族成员,包括爷爷、爸爸、叔叔、我和弟弟
首先会实现一个Element的接口,里面只有一个accept方法。所有节点实现这个接口表示是可接受访问的。
然后实现一个访问者的接口Visitor,包含了访问所有节点的方法。所有实际访问者都要实现这个接口实现自己的访问逻辑。
先把节点类展示下
public interface Element { void accept(Visitor visitor); } @Data @NoArgsConstructor public class GrandFather implements Element { //景点 private Father father; private Uncle uncle; public GrandFather(Father father, Uncle uncle) { this.father = father; this.uncle = uncle; } @Override public void accept(Visitor visitor) { visitor.visit(this); } } @Data @NoArgsConstructor public class Father implements Element { private Me me; private Brother brother; public Father(Me me, Brother brother) { this.me = me; this.brother = brother; } @Override public void accept(Visitor visitor) { visitor.visit(this); } } @AllArgsConstructor @Data public class Uncle implements Element { @Override public void accept(Visitor visitor) { visitor.visit(this); } } @AllArgsConstructor @Data public class Me implements Element { @Override public void accept(Visitor visitor) { visitor.visit(this); } } @Data public class Brother implements Element { @Override public void accept(Visitor visitor) { visitor.visit(this); } }
下面是访问者接口和它的实现类,可以看到所有的访问逻辑已经都集中到了访问者这里。
public interface Visitor { void visit(GrandFather node); void visit(Father node); void visit(Uncle node); void visit(Me node); void visit(Brother node); } public class VisitorImpl implements Visitor{ @Override public void visit(GrandFather node) { System.out.println("I am GrandFather!"); node.getFather().accept(this); node.getUncle().accept(this); } @Override public void visit(Father node) { System.out.println("I am Father!"); node.getMe().accept(this); node.getBrother().accept(this); } @Override public void visit(Uncle node) { System.out.println("I am uncle!"); } @Override public void visit(Me node) { System.out.println("I am me!"); } @Override public void visit(Brother node) { System.out.println("I am brother!"); } }
定义一个家谱类
//家谱类 @Data public class Genealogy { private Element root; } //访问家谱 public class Client { public static void main(String[] args) { GrandFather grandFather = new GrandFather(); Father father = new Father(); Uncle uncle = new Uncle(); Me me = new Me(); Brother brother = new Brother(); grandFather.setFather(father); grandFather.setUncle(uncle); father.setBrother(brother); father.setMe(me); Genealogy genealogy = new Genealogy(); genealogy.setRoot(grandFather); VisitorImpl visitor = new VisitorImpl(); visitor.visit((GrandFather)genealogy.getRoot()); } }
输出
I am GrandFather! I am Father! I am me! I am brother! I am uncle!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2021-08-17 java设计模式之责任链
2021-08-17 postman高级用法之pre-request
2021-08-17 SpringBoot读取Resource下文件的几种方式(转)