一、问题
1、将观众分为男人和女人,对歌手进行测评,当看完某个歌手的表演后,得到他们对歌手的不同评价(比如:成功、失败)
二、访问者模式
1、访问者模式(Visitor Pattern)封装一些作用于某种数据结构的各元素的操作,他可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
2、解决数据结构和操作耦合性问题
3、工作原理:在被访问的类里面加一个对外提供接待访问者的接口。
4、场景:需要对一个对象结构中的对象进行很多不同操作(这些操作彼此没有关联),同时需要避免让这些操作“污染”这些对象的类 ==> 选用访问者模式
三、说明
1、Vistor:是抽象访问者,为该对象结构中的ConcreteElement的每一个类声明一个visit操作
2、ConcreteElement:是一个具体的访问值实现每个有Visitor声明的操作,每个操作实现的部分
3、ObjectStructure:能枚举它的元素,可以提供一个高层接口,用来访问者者访问元素。
4、Element:定义一个accept 方法,接收一个访问者对象。
5、ConcreteElement:为具体元素,实现了accept方法。
6、双分派:不管类则么变化,我们都能找到期望的方法运行双分派意味着得到执行的操作取决于请求的种类和两个接受者的类型。
四、优缺点
1、优点
1)访问者模式符合单一职责原则,让程序具有优秀的扩展性、灵活性非常高。
2)访问者模式可以对功能进行统一,可以做报表、UI、拦截器、过滤器适用于数据结构相对稳定的,又经常变化功能需求的系统。
2、缺点
1)具体元素对访问者公布细节,访问者关注了其他类的内部细节,是迪米特法则不建议的,这样会造成具体元素变更的困难。
2)违背了依赖倒转原则。访问者依赖的是具体原则而不是抽象元素
五、代码
package com.hao.demo.design.visitor;
/**
* @author
* @date 2020-05-25
*/
public abstract class Person {
// 提供一个方法,让访问者可以访问
public abstract void accept(Action action);
}
package com.hao.demo.design.visitor;
/**
* @author
* @date 2020-05-25
*/
public class Man extends Person{
@Override
public void accept(Action action) {
action.getManResult(this);
}
}
package com.hao.demo.design.visitor;
/**
* @author
* @date 2020-05-25
* @description
* 1、这里使用了双分派
* 2、首先在客户端程序中,将具体状态作为参数传递Woman中(第一次分派)
* 3、Woman类调用作为参数的"具体方法"中方法getWomanResult,同时将自己(this)作为参数传入(第二次分派)
*
*/
public class Woman extends Person{
@Override
public void accept(Action action) {
action.getWomanResult(this);
}
}
package com.hao.demo.design.visitor;
/**
* @author
* @date 2020-05-25
*/
public abstract class Action {
// 得到男性的测评
public abstract void getManResult(Man man);
// 得到女性的测评
public abstract void getWomanResult(Woman woman);
}
package com.hao.demo.design.visitor;
/**
* @author
* @date 2020-05-25
*/
public class Fail extends Action{
@Override
public void getManResult(Man man) {
System.out.println("男性评价为失败");
}
@Override
public void getWomanResult(Woman woman) {
System.out.println("女性评价为失败");
}
}
package com.hao.demo.design.visitor;
/**
* @author
* @date 2020-05-25
*/
public class Success extends Action{
@Override
public void getManResult(Man man) {
System.out.println("男性给的评价是Success");
}
@Override
public void getWomanResult(Woman woman) {
System.out.println("女性给的评价是Success");
}
}
package com.hao.demo.design.visitor;
import java.util.LinkedList;
import java.util.List;
/**
* @author
* @date 2020-05-25
*/
public class ObjectStructure {
// 维护了一个集合
private List<Person> persons = new LinkedList<>();
// 增加到List
public void attach(Person person) {
persons.add(person);
}
// 移除List
public void detach(Person person) {
persons.remove(person);
}
// 现实测试的评价
public void disPlay(Action action) {
persons.forEach(person -> person.accept(action));
}
}
package com.hao.demo.design.visitor;
/**
* @author
* @date 2020-05-25
*/
public class Client {
public static void main(String[] args) {
// 创建ObjectStructure
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new Man());
objectStructure.attach(new Woman());
objectStructure.attach(new Man());
// 成功
Success success = new Success();
objectStructure.disPlay(success);
Fail fail = new Fail();
objectStructure.disPlay(fail);
// 测试增加一个待定的测评
Wait wait = new Wait();
objectStructure.disPlay(wait);
}
}
package com.hao.demo.design.visitor;
/**
* @author
* @date 2020-05-25
*/
// 增加一个待定评价
public class Wait extends Action {
@Override
public void getManResult(Man man) {
System.out.println("男性给的评价待定");
}
@Override
public void getWomanResult(Woman woman) {
System.out.println("女性给的评价待定");
}
}