設(shè)計模式學(xué)習(xí)—訪問者模式

1计贰、什么是訪問者模式钦睡?

? 訪問者設(shè)計模式的目的是表示要對對象結(jié)構(gòu)的元素執(zhí)行的操作。Visitor允許您定義一個新的操作躁倒,而不需要更改它所操作的元素的類荞怒。Visitor模式允許在不更改集合中任何對象的類的情況下定義操作。要實現(xiàn)這一點秧秉,Visitor模式建議在一個稱為Visitor類的單獨類中定義操作褐桌。這將操作從它所操作的對象集合中分離出來。對于每個要定義的新操作象迎,都會創(chuàng)建一個新的訪問者類荧嵌。

2、場景分析

我們都知道財務(wù)都是有賬本的砾淌,這個賬本就可以作為一個對象結(jié)構(gòu)啦撮,而它其中的元素有兩種,收入和支出,這滿足我們訪問者模式的要求,即元素的個數(shù)是穩(wěn)定的牵素,因為賬本中的元素只能是收入和支出。

而查看賬本的人可能有這樣幾種织中,比如老板锥涕,會計事務(wù)所的注會,財務(wù)主管狭吼,等等层坠。而這些人在看賬本的時候顯然目的和行為是不同的。

首先我們給出單子的接口刁笙,它只有一個方法accept破花。

public interface Bill {

    void accept(AccountBookViewer viewer);

}

其中的方法參數(shù)AccountBookViewer是一個賬本訪問者接口,接下來也就是實現(xiàn)類采盒,收入單子和消費單子旧乞,或者說收入和支出類。

//消費的單子
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;
    }
}
//收入單子
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;
    }
}

上面最關(guān)鍵的還是里面的accept方法磅氨,它直接讓訪問者訪問自己,這相當于一次靜態(tài)分派(文章最后進行解釋)嫡纠,當然我們也可以不使用重載而直接給方法不同的名稱烦租。

接下來是賬本訪問者接口

//賬單查看者接口(相當于Visitor)
public interface AccountBookViewer {

    //查看消費的單子
    void view(ConsumeBill bill);

    //查看收入的單子
    void view(IncomeBill bill);

}

這兩個方法是重載方法,就是在上面的元素類當中用到的除盏,當然你也可以按照訪問者模式類圖當中的方式去做叉橱,將兩個方法分別命名為viewConsumeBill和viewIncomeBill,而一般建議按照類圖上來做的

訪問者的實現(xiàn)

//老板類者蠕,查看賬本的類之一
public class Boss implements AccountBookViewer {

    private double totalIncome;

    private double totalConsume;

    //老板只關(guān)注一共花了多少錢以及一共收入多少錢窃祝,其余并不關(guān)心
    public void view(ConsumeBill bill) {
        totalConsume += bill.getAmount();
    }

    public void view(IncomeBill bill) {
        totalIncome += bill.getAmount();
    }

    public double getTotalIncome() {
        System.out.println("老板查看一共收入多少,數(shù)目是:" + totalIncome);
        return totalIncome;
    }

    public double getTotalConsume() {
        System.out.println("老板查看一共花費多少踱侣,數(shù)目是:" + totalConsume);
        return totalConsume;
    }

}
//注冊會計師類粪小,查看賬本的類之一
public class CPA implements AccountBookViewer {

    //注會在看賬本時,如果是支出抡句,則如果支出是工資探膊,則需要看應(yīng)該交的稅交了沒
    public void view(ConsumeBill bill) {
        if (bill.getItem().equals("工資")) {
            System.out.println("注會查看工資是否交個人所得稅。");
        }
    }
    //如果是收入待榔,則所有的收入都要交稅
    public void view(IncomeBill bill) {
        System.out.println("注會查看收入交稅了沒逞壁。");
    }

}

老板只關(guān)心收入和支出的總額,而注會只關(guān)注該交稅的是否交稅

接下來是賬本類锐锣,它是當前訪問者模式例子中的對象結(jié)構(gòu)

//賬本類(相當于ObjectStruture)
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);
        }
    }
}

賬本類當中有一個列表腌闯,這個列表是元素(Bill)的集合,這便是對象結(jié)構(gòu)的通常表示雕憔,它一般會是一堆元素的集合姿骏,不過這個集合不一定是列表,也可能是樹橘茉,鏈表等等任何數(shù)據(jù)結(jié)構(gòu)工腋,甚至是若干個數(shù)據(jù)結(jié)構(gòu)姨丈。其中show方法,就是賬本類的精髓擅腰,它會枚舉每一個元素蟋恬,讓訪問者訪問。

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();
    }
}

上面的代碼中趁冈,可以這么理解歼争,賬本以及賬本中的元素是非常穩(wěn)定的,這些幾乎不可能改變渗勘,而最容易改變的就是訪問者這部分沐绒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市旺坠,隨后出現(xiàn)的幾起案子乔遮,更是在濱河造成了極大的恐慌,老刑警劉巖取刃,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹋肮,死亡現(xiàn)場離奇詭異,居然都是意外死亡璧疗,警方通過查閱死者的電腦和手機坯辩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來崩侠,“玉大人漆魔,你說我怎么就攤上這事∪匆簦” “怎么了改抡?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長僧家。 經(jīng)常有香客問我雀摘,道長,這世上最難降的妖魔是什么八拱? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任阵赠,我火速辦了婚禮,結(jié)果婚禮上肌稻,老公的妹妹穿的比我還像新娘清蚀。我一直安慰自己,他們只是感情好爹谭,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布枷邪。 她就那樣靜靜地躺著,像睡著了一般诺凡。 火紅的嫁衣襯著肌膚如雪东揣。 梳的紋絲不亂的頭發(fā)上践惑,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音嘶卧,去河邊找鬼尔觉。 笑死,一個胖子當著我的面吹牛芥吟,可吹牛的內(nèi)容都是我干的侦铜。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钟鸵,長吁一口氣:“原來是場噩夢啊……” “哼钉稍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起棺耍,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤贡未,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后烈掠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體羞秤,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年左敌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俐镐。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡矫限,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出佩抹,到底是詐尸還是另有隱情叼风,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布棍苹,位于F島的核電站无宿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏枢里。R本人自食惡果不足惜孽鸡,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望栏豺。 院中可真熱鬧彬碱,春花似錦、人聲如沸奥洼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽灵奖。三九已至嚼沿,卻和暖如春估盘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背骡尽。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工遣妥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人爆阶。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓燥透,卻偏偏與公主長得像,于是被迫代替她去往敵國和親辨图。 傳聞我的和親對象是個殘疾皇子班套,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355