文章目录
- 1. 引入
- 2. 访问模式的特性
- 3. UML
- 4. demo
1. 引入
我们都知道 计算机程序 = 算法 + 数据结构
。
再举一个例子,面向对象编程时,一个类定义通常也是由属性
和方法
组成的。也就是说,一个类的行为在定义时就完全确定了。
而访问者模式(Visitor),就是一种用来将数据结构和算法进行解耦的设计模式。符合开放关闭原则
访问者模式是Gof 23种设计模式之一,维基百科的介绍如下
wiki简介
2. 访问模式的特性
- 设计目的:将固定的数据结构与灵活的算法解耦
- 优势:可以不改动类结构为对象添加虚拟的方法
- 劣势:扩展原始的类时,要考虑修改所有的visitor,不利于扩展
- 适用场景:数据结构相对稳定的场景,如ASM框架中
网上很多教程会强调很多不同类可以实现不同的方法,个人认为这只是访问模式的扩展特性,其核心还是为固定的结构扩展虚拟的方法
3. UML
«interface» IVisitor visit(IElement element) Visitor void visit Element String name String version void accept «interface» IElement accept(Ivisitor visitor) client 调用
4. demo
场景:手机都是相对固定的组成,现在要添加5G功能,代码如下
- 入口
/**
* 程序 = 数据结构 + 算法
* visitor模式
* 目的:让 数据结构 与 算法 解耦,符合开放关闭原则
* 优势:可以不改动类结构为对象添加虚拟的方法 (wiki https://en.wikipedia.org/wiki/Visitor_pattern#Overview)
* 劣势:扩展原始的类时,要考虑修改所有的visitor,不利于扩展
* 适用场景:数据结构非常稳定
*/
public class Client {
public static void main(String[] args) {
HwPhone phone = new HwPhone("p40", "华为");
IPhone iPhone = new IPhone("iphone11", "apple");
// 扩展一个执行5G的方法
IVisitor fifthVisitor= new FifthVisitor();
phone.accept(fifthVisitor);
iPhone.accept(fifthVisitor);
}
}
- Visitor
/**
* 访问者接口
* @Author
* @Date 7:15 下午 2020/9/24
*/
public interface IVisitor {
// 访问华为phone
void visit(HwPhone phone);
// 访问IPhone
void visit(IPhone phone);
}
/**
* 5G扩展
* @Author
* @Date 3:29 下午 2020/9/27
*/
public class FifthVisitor implements IVisitor{
@Override
public void visit(HwPhone phone) {
String msg = "【" + phone.getName() + phone.getVersion() + "】5G通信中...";
System.out.println(msg);
}
@Override
public void visit(IPhone phone) {
String msg = "【" + phone.getName() + phone.getVersion() + "】暂不支持5G";
System.out.println(msg);
}
}
- Phone
需要扩展虚拟方法的类
/**
* 手机接口
* @Author
* @Date 7:09 下午 2020/9/24
*/
public interface CellPhone {
// 接受visitor的访问和操作(对自己进行操作)
void accept(IVisitor visitor);
}
public class HwPhone implements CellPhone{
private String version;
private String name;
public HwPhone(String version, String name) {
this.version = version;
this.name = name;
}
@Override
public void accept(IVisitor visitor) {
// 调用visitor的增强方法
visitor.visit(this);
// 此处甚至可以调用visitor中的其他方法
// 例如,只visit name
}
public String getVersion() {
return version;
}
public String getName() {
return name;
}
}
/**
* 苹果手机
* @Author
* @Date 7:39 下午 2020/9/24
*/
public class IPhone implements CellPhone {
private String version;
private String name;
public IPhone(String version, String name) {
this.version = version;
this.name = name;
}
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
public String getVersion() {
return version;
}
public String getName() {
return name;
}
}
- 运行结果
可以看到,在没有修改phone类的情况下,通过accept方法可以为其灵活扩展类中不存在的虚拟方法