設計模式-訪問者模式(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