1.什么是访问者模式?
比如我有一个账单,账单有收入,支出两个固定方法。但是访问账单的人不确定,有可能是一个或者多个。
2.访问者模式有两个特点
一般被访问的东西所持有的方法是固定的,就像账单只有收入和支出两个功能。而访问者是不固定的。
数据操作与数据结构相分离:频繁的更改数据,但不结构不变。比如:虽然每一天账单的数据都会变化(数据变化),但是只有两类数据,就是支出和收入(结构不变)。
简化如下图:
例子:
import java.util.ArrayList;
import java.util.List;
/**
* 创建一个账单接口,有接收访问者的功能
*
* @author hgx
*
*/
interface Bill {
void accept(AccountBookView viewer);
}
/**
* 消费单子
*
* @author hgx
*
*/
class ConsumerBill implements Bill {
private String item;
private double amount;
public ConsumerBill(String item, double amount) {
this.item = item;
this.amount = amount;
}
public void accept(AccountBookView viewer) {
viewer.view(this);
}
public String getItem() {
return item;
}
public double getAmount() {
return amount;
}
}
/**
* 收入单子
*
* @author hgx
*
*/
class IncomeBill implements Bill {
private String item;
private double amount;
public IncomeBill(String item, double amount) {
this.item = item;
this.amount = amount;
}
public void accept(AccountBookView viewer) {
viewer.view(this);
}
public String getItem() {
return item;
}
public double getAmount() {
return amount;
}
}
/**
* 访问者接口
*
* @author hgx
*
*/
interface AccountBookView {
// 查看消费的单子
void view(ConsumerBill consumerBill);
// 查看收入单子
void view(IncomeBill incomeBill);
}
// 老板类:访问者是老板,主要查看总支出和总收入
class Boss implements AccountBookView {
private double totalConsumer;
private double totalIncome;
// 查看消费的单子
public void view(ConsumerBill consumerBill) {
totalConsumer = totalConsumer + consumerBill.getAmount();
}
// 查看收入单子
public void view(IncomeBill incomeBill) {
totalIncome = totalIncome + incomeBill.getAmount();
}
public void getTotalConsumer() {
System.out.println("老板一共消费了" + totalConsumer);
}
public void getTotalIncome() {
System.out.println("老板一共收入了" + totalIncome);
}
}
/**
* 会计类:访问者是会计,主要记录每笔单子
*
* @author hgx
*
*/
class CPA implements AccountBookView {
int count = 0;
// 查看消费的单子
public void view(ConsumerBill consumerBill) {
count++;
if (consumerBill.getItem().equals("消费")) {
System.out.println("第" + count + "个单子消费了:" + consumerBill.getAmount());
}
}
// 查看收入单子
public void view(IncomeBill incomeBill) {
if (incomeBill.getItem().equals("收入")) {
System.out.println("第" + count + "个单子收入了:" + incomeBill.getAmount());
}
}
}
/**
* 账单类:用于添加账单,和为每一个账单添加访问者
*
* @author hgx
*
*/
class AccountBook {
private List<Bill> listBill = new ArrayList<Bill>();
// 添加单子
public void add(Bill bill) {
listBill.add(bill);
}
// 为每个账单添加访问者
public void show(AccountBookView viewer) {
for (Bill b : listBill) {
b.accept(viewer);
}
}
}
/*
*测试类
*/
public class Test {
public static void main(String[] args) {
// 创建消费和收入单子
Bill consumerBill = new ConsumerBill("消费", 3000);
Bill incomeBill = new IncomeBill("收入", 5000);
Bill consumerBill2 = new ConsumerBill("消费", 4000);
Bill incomeBill2 = new IncomeBill("收入", 8000);
// 添加单子
AccountBook accountBook = new AccountBook();
accountBook.add(consumerBill);
accountBook.add(incomeBill);
accountBook.add(consumerBill2);
accountBook.add(incomeBill2);
// 创建访问者
Boss boss = new Boss();
CPA cpa = new CPA();
// 接受访问者
accountBook.show(boss);
accountBook.show(cpa);
// boss查看总收入和总消费
boss.getTotalConsumer();
boss.getTotalIncome();
}
}
测试结果:
第1个单子消费了:3000.0
第1个单子收入了:5000.0
第2个单子消费了:4000.0
第2个单子收入了:8000.0
老板一共消费了:7000.0
老板一共收入了:13000.0
本文按照个人理解,全部通俗化解释,如有错误希望指出 。