设计模式-访问者模式(Visitor Pattern)
定义
封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下,定义作用于这些元素的新操作。
主要将数据结构与数据操作分离。
优缺点
优点: 1、符合单一职责原则。 2、优秀的扩展性。 3、灵活性。
缺点: 1、具体元素对访问者公布细节,违反了迪米特原则。 2、具体元素变更比较困难。 3、违反了依赖倒置原则,依赖了具体类,没有依赖抽象。
使用场景
1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。
2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。
实现
我们可以通过生活中的一些例子来理解它,比如家里来了客人,客人就是访问者,他可以做一些事情,但是又不能做全部的事情; 又或者说去网吧上网的小明,小明也是访问者,他可以在网吧玩游戏、看视频、听音乐等等,但是不能破坏网吧中的设备等等。按照这么理解,我们大概就可以知道访问者模式主要是做什么了。
访问者模式主要由这五个角色组成,抽象访问者(Visitor)、具体访问者(ConcreteVisitor)、抽象节点(Node)、具体节点(ConcreteNode)和结构对象(ObjectStructure)。
抽象访问者(Visitor)角色:声明了一个或者多个方法操作,形成所有的具体访问者角色必须实现的接口。
具体访问者(ConcreteVisitor)角色:实现抽象访问者所声明的接口,也就是抽象访问者所声明的各个访问操作。
抽象节点(Node)角色:声明一个接受操作,接受一个访问者对象作为一个参数。
具体节点(ConcreteNode)角色:实现了抽象节点所规定的接受操作。
结构对象(ObjectStructure)角色:有如下的责任,可以遍历结构中的所有元素。
我们使用一个简单的示例来加以说明。 图书馆有一台电脑,但是只能玩游戏和看图片。张三和李四先后使用了这台电脑,那么他们就可以当作是访问者。 首先定义一个抽象的访问者,拥有玩游戏和看图片的方法;然后再定义一个抽象节点电脑,接受这个请求。
抽象访问者(Visitor)角色
//抽象访问者(Visitor)角色 interface Visitor { //可以访问游戏 void visit(Games games); //可以访问图片 void visit(Photos photos); } 复制代码
抽象节点(Node)角色
//抽象节点(Node)角色:声明一个接受操作,接受一个访问者对象作为一个参数。 interface Computer { void accept(Visitor visitor); } 复制代码
具体节点(ConcreteNode)角色
//具体节点(ConcreteNode)角色:实现了抽象节点所规定的接受操作。 class Games implements Computer { @Override public void accept(Visitor visitor) { visitor.visit(this); } public String play() { return "play Games"; } } 复制代码
//具体节点(ConcreteNode)角色:实现了抽象节点所规定的接受操作。 class Photos implements Computer { @Override public void accept(Visitor visitor) { visitor.visit(this); } public String watch() { return "watch photos"; } } 复制代码
结构对象(ObjectStructure)角色
//结构对象(ObjectStructure)角色:有如下的责任,可以遍历结构中的所有元素。 class ObjectStructure { private List<Computer> computers = new ArrayList<Computer>(); public void action(Visitor visitor) { for (Computer c : computers) { c.accept(visitor); } } public void add(Computer computer) { computers.add(computer); } } 复制代码
验证结果
class Test { public static void main(String[] args) { // 创建一个结构对象 ObjectStructure os = new ObjectStructure(); // 给结构增加一个节点 os.add(new Games()); // 给结构增加一个节点 os.add(new Photos()); // 创建2个访问者 Visitor visitorZhangSan = new PersonVisitor("zhangsan"); Visitor visitorLisi = new PersonVisitor("lisi"); os.action(visitorZhangSan); os.action(visitorLisi); } } 复制代码
zhangsan-----play Games zhangsan-----watch photos lisi-----play Games lisi-----watch photos
作者:小Fuคิดถึง
链接:https://juejin.cn/post/7012893654075310094