1. 程式人生 > >設計模式-訪問者模式(Visitor)

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