* 24种设计模式——访问者模式

来源:互联网 发布:淘宝自带的折扣工具 编辑:程序博客网 时间:2024/06/06 11:45

定义:封装一些作用于某种数据结构(List/Set/Map)中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

一、访问员工信息


1. 访问者接口

public interface IVisitor {//首先,定义我可以访问普通员工public void visit(CommonEmployee commonEmployee);//其次,定义我还可以访问部门经理public void visit(Manager manager);}
2. 访问者实现

public class Visitor implements IVisitor{//访问普通员工,打印出报表public void visit(CommonEmployee commonEmployee) {System.out.println(this.getCommonEmployee(commonEmployee));}//访问部门经理,打印出报表public void visit(Manager manager) {System.out.println(this.getManagerInfo(manager));}//组装出基本信息private String getBasicInfo(Employee employee){String info = "姓名:"+employee.getName()+"\t";info = info+"性别:"+(employee.getSex()==Employee.FEMALE?"女":"男")+"\t";info = info+"薪水:"+employee.getSalary()+"\t";return info;}//组装出部门经理的信息private String getManagerInfo(Manager manager){String basicInfo = this.getBasicInfo(manager);String otherInfo = "业绩:"+manager.getPerformance()+"\t";return basicInfo + otherInfo;}//组装出普通员工信息private String getCommonEmployee(CommonEmployee commonEmployee){String basicInfo = this.getBasicInfo(commonEmployee);String otherInfo = "工作:"+commonEmployee.getJob()+"\t";return basicInfo + otherInfo;}}
3. 抽象员工类

public abstract class Employee {public final static int MALE = 0;//0代表是男性public final static int FEMALE = 1;//1代表是女性//甭管是谁,都有工资private String name;//只要是员工那就有薪水private int salary;//性别很重要private int sex;get()/set();//我允许一个访问者访问public abstract void accept(IVisitor visitor);}
4. 普通员工

public class CommonEmployee extends Employee{//工作内容,这非常重要,以后的职业规划就是靠它了private String job;public String getJob() {return job;}public void setJob(String job) {this.job = job;}//我允许访问者访问public void accept(IVisitor visitor) {visitor.visit(this);}}
5. 管理层员工

public class Manager extends Employee{//这类人物的职责非常明确:业绩private String performance;public String getPerformance() {return performance;}public void setPerformance(String performance) {this.performance = performance;}//部门经理允许访问者访问public void accept(IVisitor visitor) {visitor.visit(this);}}
6. 场景类

public class Client {public static void main(String[] args) {for(Employee emp:mockEmployee()){emp.accept(new Visitor());}}//模拟出公司的人员情况,我们可以想象这个数据是通过持久层传递过来的public static List<Employee> mockEmployee(){List<Employee> empList = new ArrayList<Employee>();//产生张三这个员工CommonEmployee zhangSan = new CommonEmployee();zhangSan.setJob("编写Java程序,绝对的蓝领、苦工加搬运工");zhangSan.setName("张三");zhangSan.setSalary(1800);zhangSan.setSex(Employee.MALE);empList.add(zhangSan);//产生李四这个员工CommonEmployee liSi = new CommonEmployee();liSi.setJob("页面美工、审美素质太不流行了");liSi.setName("李四");liSi.setSalary(1900);liSi.setSex(Employee.FEMALE);empList.add(liSi);//再产生一个经理Manager wangWu = new Manager();wangWu.setName("王五");wangWu.setPerformance("基本上是负值,但是我会拍马屁呀");wangWu.setSalary(18750);wangWu.setSex(Employee.MALE);empList.add(wangWu);return empList;}}
二、访问者模式的定义

定义:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。

1. 抽象元素

public abstract class Element {//定义业务逻辑public abstract void doSomething();//允许谁来访问public abstract void accept(IVisitor visitor);}
2. 具体元素

public class ConcreteElement1 extends Element{//完善业务逻辑public void doSomething() {//业务处理}//允许那个访问者访问public void accept(IVisitor visitor) {visitor.visit(this);}}
&

public class ConcreteElement2 extends Element{//完善业务逻辑public void doSomething() {//业务处理}//允许那个访问者访问public void accept(IVisitor visitor) {visitor.visit(this);}}
3. 抽象访问者

public interface IVisitor {//可以访问哪些对象public void visit(ConcreteElement1 el1);public void visit(ConcreteElement2 el2);}
4. 具体访问者

public class Visitor implements IVisitor{//访问el1元素public void visit(ConcreteElement1 el1) {el1.doSomething();}//访问el2元素public void visit(ConcreteElement2 el2) {el2.doSomething();}}
5. 结构对象

public class ObjectStruture {//对象生成器,这里通过一个工厂方法模式模拟public static Element createElement(){Random rand = new Random();if(rand.nextInt(100)>50){return new ConcreteElement1();}else{return new ConcreteElement2();}}}
6. 场景类

public class Client {public static void main(String[] args) {for(int i = 0;i < 10;i++){//获得元素对象Element el = ObjectStruture.createElement();//接受访问者访问el.accept(new Visitor());}}}
三、访问者模式的应用

1. 优点

符合单一职责原则:具体元素角色也就是Employee抽象类的两个子类负责数据的加载,而Visitor类则负责报表的展现,两个不同的职责非常明确地分离开来。

优秀的扩展性:由于职责分开,继续增加对数据的操作非常快捷,如,现在要增加一份给大老板的报表,这份报表格式又有所不同,直接在Visitor中增加一个方法,传递数据后进行整理打印。

2. 缺点

具体元素对访问者公布细节:访问者要访问一个类就必然要求这个类公布一些方法和数据,也就是说访问者关注了其他类的内部细节,这是迪米特法则所不建议的。

具体元素变更比较困难:具体元素角色的增加、删除、修改都是比较困难的,就上面那个例子,要是想增加一个成员变量,如年龄age,Visitor就需要修改,如果Visitor是一个还好办,多个就很复杂了。

3. 使用场景

1)一个对象结构(List/Set/Map等)包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作,也就是说迭代器模式已经不能胜任的情景。

2)需要对一个对象结构(List/Set/Map等)中的对象进行很多不同并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。