一、定义
访问者模式,表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
此模式的目的事要把处理从数据结构分离出来。很多系统可以按照算法和数据结构分开,如果系统有比较稳定的数据结构,又有易于变化的算法的话,使用此模式是比较合适的。
访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为计中到一个访问者对象中。
二、UML类图
三、实现
- 访问抽象类
package com.jthao.design.des.visitor;
public interface AccountBookViewer {
// 查看消费的单子
void view(ConsumeBill bill);
// 查看收入的单子
void view(IncomeBill bill);
}
- 具体访问类A
package com.jthao.design.des.visitor;
public class Boss implements AccountBookViewer {
private double totalIncome;
private double totalConsume;
// 老板只关注一共花了多少钱以及一共收入多少钱,其余并不关心
public void view(ConsumeBill bill) {
totalConsume += bill.getAmount();
}
public void view(IncomeBill bill) {
totalIncome += bill.getAmount();
}
public double getTotalIncome() {
System.out.println("老板查看一共收入多少,数目是:" + totalIncome);
return totalIncome;
}
public double getTotalConsume() {
System.out.println("老板查看一共花费多少,数目是:" + totalConsume);
return totalConsume;
}
}
- 具体访问类B
package com.jthao.design.des.visitor;
public class CPA implements AccountBookViewer {
// 注会在看账本时,如果是支出,则如果支出是工资,则需要看应该交的税交了没
public void view(ConsumeBill bill) {
if (bill.getItem().equals("工资")) {
System.out.println("注会查看工资是否交个人所得税。");
}
}
// 如果是收入,则所有的收入都要交税
public void view(IncomeBill bill) {
System.out.println("注会查看收入交税了没。");
}
}
- 元素接口类
package com.jthao.design.des.visitor;
public interface Bill {
void accept(AccountBookViewer viewer);
}
- 元素实现类A
package com.jthao.design.des.visitor;
public class ConsumeBill implements Bill {
private double amount;
private String item;
public ConsumeBill(double amount, String item) {
super();
this.amount = amount;
this.item = item;
}
public void accept(AccountBookViewer viewer) {
viewer.view(this);
}
public double getAmount() {
return amount;
}
public String getItem() {
return item;
}
}
- 元素实现类B
package com.jthao.design.des.visitor;
public class IncomeBill implements Bill {
private double amount;
private String item;
public IncomeBill(double amount, String item) {
super();
this.amount = amount;
this.item = item;
}
public void accept(AccountBookViewer viewer) {
viewer.view(this);
}
public double getAmount() {
return amount;
}
public String getItem() {
return item;
}
}
- 对象结构类
package com.jthao.design.des.visitor;
import java.util.ArrayList;
import java.util.List;
public class AccountBook {
// 单子列表
private List<Bill> billList = new ArrayList<Bill>();
// 添加单子
public void addBill(Bill bill) {
billList.add(bill);
}
// 供账本的查看者查看账本
public void show(AccountBookViewer viewer) {
for (Bill bill : billList) {
bill.accept(viewer);
}
}
}
- 测试类
package com.jthao.design.des.visitor;
public class Client {
public static void main(String[] args) {
AccountBook accountBook = new AccountBook();
// 添加两条收入
accountBook.addBill(new IncomeBill(10000, "卖商品"));
accountBook.addBill(new IncomeBill(12000, "卖广告位"));
// 添加两条支出
accountBook.addBill(new ConsumeBill(1000, "工资"));
accountBook.addBill(new ConsumeBill(2000, "材料费"));
AccountBookViewer boss = new Boss();
AccountBookViewer cpa = new CPA();
// 两个访问者分别访问账本
accountBook.show(cpa);
accountBook.show(boss);
((Boss) boss).getTotalConsume();
((Boss) boss).getTotalIncome();
}
}