"圍觀"設計模式(24)--行為型之訪問者模式(Visitor Pattern)
來源:程序員人生 發布時間:2016-07-20 08:31:27 閱讀次數:3521次
訪問者模式:表示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個訪問的接口便可。
源代碼下載
設計模式源代碼下載
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈