国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php框架 > 框架设计 > "围观"设计模式(24)--行为型之访问者模式(Visitor Pattern)

"围观"设计模式(24)--行为型之访问者模式(Visitor Pattern)

来源:程序员人生   发布时间:2016-07-20 08:31:27 阅读次数:2073次

访问者模式:表示1个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的条件下定义作用于这些元素的新操作。


个人理解

访问者模式,扩大能力很好,符合开闭原则,对扩大开放,对修改关闭。但是从类的实现情况来看,访问者类和元素类相互之间依赖,依赖关系较强,不过可以通过抽象类或接口的情势,将依赖关系转移到上层抽象类或接口中,从而下降对实现类的依赖。访问者模式的动身点:业务规则要求遍历多个不同的对象。访问者模式是对迭代器模式的扩充,他可以访问不同的对象,实现遍历的目的。


案例解析


模板案例


访问者模式中的角色


1. Visitor--抽象访问者:声明访问者可以访问哪些接口。

2. ConcreteVisitor--具体的访问者:具体实现抽象访问者中的方法。

3. Element--抽象元素:声明接收哪1类访问者的访问。

4. ConcreteELe--具体元素:具体实现抽象元素中定义的方法。


访问者模式类结构图



主要代码


元素角色类

public abstract class Element { // 定义方法 public abstract void doSomething(); // 定义接收的视察者 public abstract void accept(Vistor vistor); }
具体实现类

public class ConcreteEle1 extends Element { @Override public void doSomething() { System.out.println("1...Eat Food!"); } @Override public void accept(Vistor vistor) { vistor.vist(this); } }

访问者角色抽象类


public interface Vistor { public void vist(Element animal); }

具体实现类

public class ConcreteVistor1 implements Vistor { @Override public void vist(Element ele) { ele.doSomething(); } }

利用案例拓展:乌龟喂食问题


场景介绍

两个乌龟吃饭的问题,用访问者模式来设计的话,Vistor角色应当是我,而元素类则是这两个乌龟。


类的结构图


主要代码

抽象类

public abstract class Animal { // 定义吃饭的方法 public abstract void eatFood(); // 定义接收的视察者 public abstract void accept(Vistor vistor); }
具体实现类
public class X extends Animal { @Override public void eatFood() { System.out.println("X...Eat Food!"); } @Override public void accept(Vistor vistor) { vistor.vist(this); } }

访问者类

public interface Vistor { public void vist(Animal animal); }
public class WY implements Vistor { @Override public void vist(Animal animal) { animal.eatFood(); } }

测试类

public class MainTest { public static void main(String[] args) { Animal y = new Y(); Animal x = new X(); Vistor vistor = new WY(); y.accept(vistor); x.accept(vistor); } }

利用案例拓展:查看员工信息


类结构图


主要代码

public abstract class Employee { private String name; private int salary; private String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public abstract void accept(Visitor visitor); }

public class CommonEmployee extends Employee { private String job; @Override public void accept(Visitor visitor) { visitor.visit(this); } public String getJob() { return job; } public void setJob(String job) { this.job = job; } }<span style="font-size:18px;"> </span>
访问者
public interface Visitor { public void visit(CommonEmployee commonEmp); public void visit(Manager manager); }

具体的实现类

public class ConcreteVisitor implements Visitor { @Override public void visit(CommonEmployee commonEmp) { System.out.println(this.getCommonEmpInfo(commonEmp)); } @Override public void visit(Manager manager) { System.out.println(this.getManagerInfo(manager)); } public String getBasicInfo(Employee employee) { String info = "姓名:" + employee.getName() + " "; info += "工资:" + employee.getSalary() + " "; info += "性别:" + employee.getSex() + " "; return info; } public String getCommonEmpInfo(CommonEmployee commonEmp) { String baseInfo = getBasicInfo(commonEmp); String otherInfo = commonEmp.getJob(); return baseInfo + otherInfo; } public String getManagerInfo(Manager manager) { String baseInfo = getBasicInfo(manager); String otherInfo = manager.getPerform(); return baseInfo + otherInfo; } }
测试类
public class MainTest { static List<Employee> empList = new ArrayList<Employee>(); static { CommonEmployee commonEmp = new CommonEmployee(); commonEmp.setName("wy"); commonEmp.setSalary(1000); commonEmp.setSex("man"); commonEmp.setJob("IT"); empList.add(commonEmp); CommonEmployee commonEmp2 = new CommonEmployee(); commonEmp2.setName("w"); commonEmp2.setSalary(2000); commonEmp2.setSex("man"); commonEmp2.setJob("code"); empList.add(commonEmp2); CommonEmployee commonEmp3 = new CommonEmployee(); commonEmp3.setName("wang"); commonEmp3.setSalary(5000); commonEmp3.setSex("woman"); commonEmp3.setJob("销售"); empList.add(commonEmp3); Manager manager = new Manager(); manager.setName("wyy"); manager.setPerform("好"); manager.setSalary(10000); manager.setSex("man"); empList.add(manager); Manager manager2 = new Manager(); manager2.setName("wangyang"); manager2.setPerform("优秀"); manager2.setSalary(20000); manager2.setSex("man"); empList.add(manager2); } public static void main(String[] args) { for (Employee emp : empList) { emp.accept(new ConcreteVisitor()); } } }


访问者模式的优点

1. 符合单1职责原则:元素角色只负责数据的加载,Visitor中负责报表的展现。

2. 扩大性好,继续增加其他的类通过访问者模式可以很容易的进行扩大。


访问者模式的缺点

1. 具体的元素暴露给访问者具体的实现细节,理论上这应当尽力避免的,背背了最少知道原则。

2. 背背了依赖颠倒原则,但是我感觉软件后期再改动的时候,可能会这样,但是如果开始进行设计时就已设计好了,应当不会背背依赖颠倒原则,比如说拓展例子中,可以将访问的信息移动到其元素中实现,而访问者只需要提供1个访问的接口便可。


源代码下载

设计模式源代码下载



生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生