设计模式-访问者模式(Visitor)
访问者模式是行为模式的一种。访问者模式的基本想法是,软件系统中拥有一个由许多对象构成的、比较稳定的对象结构,这些对象的类都拥有一个accept方法用来接受访问者的访问。访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素做不同的处理。
角色和职责:
1.访问者(Visitor):
访问不同的Concrete Element
2.具体访问者(Concrete Visitor)-Boss、CPA:
具体的访问类,它需要给出对每一个元素类访问时所产生的具体行为
3.元素接口(Element)-Bill:
元素接口或者抽象类,它定义了一个接受访问者的方法(Accept),其意义是指每一个元素都要可以被访问者访问
4.具体元素类(ConcreteElement)-ConcreteElementA、ConcreteElementB:
具体的元素类,它提供接受访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法
5.对象结构(ObjectStructure)-AccountBook
:
定义当中所说的对象结构,对象结构是一个抽象表述,它内部管理了元素集合,并且可以迭代这些元素供访问者访问。
UML图:
具体代码:
/** * 访问者 */ public interface Visitor { void visitor(ConsumeBill consumeBill);//消费情况 void visitor(IncomeBill incomeBill);//收入情况 }
/** * 访问者:老板 */ public class Boss implements Visitor{ private Double totalConsumeMoney = 0d;//消费总金额 private Double totalIncomeMoney = 0d;//收入总金额 @Override public void visitor(ConsumeBill consumeBill) { totalConsumeMoney += consumeBill.getMoney(); } @Override public void visitor(IncomeBill incomeBill) { totalIncomeMoney += incomeBill.getMoney(); } public void display(){ System.out.println("总收入:"+this.totalIncomeMoney+",总消费:"+this.totalConsumeMoney); } }
/** * 访问者:会计访问,做操作 */ public class CPA implements Visitor{ @Override public void visitor(ConsumeBill consumeBill) { if(consumeBill.getType().equalsIgnoreCase("工资")){//公司消费工资,也是要给税的 System.out.println("发工资"+consumeBill.getMoney()+"元,交税"); } } @Override public void visitor(IncomeBill incomeBill) { //会计做账,每一笔收入要给税 System.out.println(incomeBill.getType()+",收入金额:"+incomeBill.getMoney()+"元,"+"交税"); } }
/** * element :元素接口 */ public interface Bill { void accept(Visitor visitor); }
/** * 消费情况 */ public class ConsumeBill implements Bill{ private Double money;//消费金额 private String type;//消费类型 public ConsumeBill(Double money,String type){ this.money = money; this.type = type; } @Override public void accept(Visitor visitor) { visitor.visitor(this); } public Double getMoney() { return money; } public String getType() { return type; } }
/** * 收入情况 */ public class IncomeBill implements Bill{ private Double money;//收入金额 private String type;//收入类型 public IncomeBill(Double money,String type){ this.money = money; this.type = type; } @Override public void accept(Visitor visitor) { visitor.visitor(this); } public Double getMoney() { return money; } public String getType() { return type; } }
/** * 对象结构: 帐簿 */ public class AccountBook { private List<Bill> list = new ArrayList<Bill>(); /** * 添加流水 * @param bill */ public void add(Bill bill){ list.add(bill); } /** * 供账本的查看者查看账本 * @param visitor */ public void show(Visitor visitor){ for(Bill bill:list){ bill.accept(visitor); } } }
public class Main { public static void main(String[] args) { //添加消费记录 ConsumeBill consumeBillCloth = new ConsumeBill(23.24,"进购打印机"); ConsumeBill consumeBillShoes = new ConsumeBill(212.99,"进购桌子"); ConsumeBill consumeBillSalary = new ConsumeBill(3000.00,"工资"); IncomeBill incomeBillAlipay = new IncomeBill(300.66,"卖维护"); IncomeBill incomeBillWechat = new IncomeBill(123.88,"卖软件"); //帐蒲 AccountBook accountBook = new AccountBook(); accountBook.add(consumeBillCloth); accountBook.add(consumeBillShoes); accountBook.add(consumeBillSalary); accountBook.add(incomeBillAlipay); accountBook.add(incomeBillWechat); //老板过来访问 Boss boss = new Boss(); accountBook.show(boss); boss.display(); System.out.println("-------------------"); //会计过来访问 CPA cpa = new CPA(); accountBook.show(cpa); } }
结果:
总收入:424.54,总消费:3236.23
-------------------
发工资3000.0元,交税
卖维护,收入金额:300.66元,交税
卖软件,收入金额:123.88元,交税
使用场景:
(1)对象结构比较稳定,但经常需要在此对象结构上定义新的操作。
(2)需要对一个对象结构中的对象进行很多不同的且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
源码地址:https://github.com/qjm201000/design_pattern_visitor.git