Java進階篇設計模式之十 ---- 訪問者模式和中介者模式

前言

上一篇中咱們學習了行爲型模式的解釋器模式(Interpreter Pattern)和迭代器模式(Iterator Pattern)。本篇則來學習下行爲型模式的兩個模式,訪問者模式(Visitor Pattern)和中介者模式(Mediator Pattern)。html

訪問者模式

簡介java

訪問者模式(VisitorPattern),顧名思義使用了這個模式後就能夠在不修改已有程序結構的前提下,經過添加額外的訪問者來完成對已有代碼功能的提高,它屬於行爲模式。訪問者模式的目的是封裝一些施加於某種數據結構元素之上的操做。一旦這些操做須要修改的話,接受這個操做的數據結構則能夠保持不變。
其主要目的是將數據結構與數據操做分離。git

訪問者模式能夠說是設計模式中最難以理解的一個模式,由於相比其它模式而言,它過於」繞「了。可是咱們能夠經過生活中的一些例子來理解它,好比家裏來了客人,客人就是訪問者,他能夠作一些事情,可是又不能作所有的事情; 又或者說去網吧上網的小明,小明也是訪問者,他能夠在網吧玩遊戲、看視頻、聽音樂等等,可是不能破壞網吧中的設備等等。按照這麼理解,咱們大概就能夠知道訪問者模式主要是作什麼了。github

訪問者模式主要由這五個角色組成,抽象訪問者(Visitor)、具體訪問者(ConcreteVisitor)、抽象節點(Node)、具體節點(ConcreteNode)和結構對象(ObjectStructure)。設計模式

  • 抽象訪問者(Visitor)角色:聲明瞭一個或者多個方法操做,造成全部的具體訪問者角色必須實現的接口。
  • 具體訪問者(ConcreteVisitor)角色:實現抽象訪問者所聲明的接口,也就是抽象訪問者所聲明的各個訪問操做。
  • 抽象節點(Node)角色:聲明一個接受操做,接受一個訪問者對象做爲一個參數。
  • 具體節點(ConcreteNode)角色:實現了抽象節點所規定的接受操做。
  • 結構對象(ObjectStructure)角色:有以下的責任,能夠遍歷結構中的全部元素。

示例圖以下:
在這裏插入圖片描述微信

這裏爲了方便理解,咱們使用一個簡單的示例來加以說明。
圖書館有一臺電腦,有兩個帳戶,其中一個是管理員的帳戶,擁有全部權限,可是設置了密碼;另外一個帳戶是不須要密碼,可是隻能玩遊戲和看圖片。張三和李四前後使用了這臺電腦,那麼他們就能夠看成是訪問者。
那麼咱們即可以根據這裏例子來使用訪問者模式進行開發,首先定義一個抽象的訪問者,擁有玩遊戲和看圖片的方法;而後再定義一個抽象節點電腦,接受這個請求。
那麼這個抽象類的代碼以下:數據結構

interface Visitor {
   void visit(Games games);
   void visit(Photos photos);
}

interface Computer {
   void accept(Visitor visitor);
}

定義好該抽象類以後,咱們須要設計不一樣的訪問者對節點進行不一樣的處理。而且須要設計具體節點類實現剛剛抽象節點的方法。ide

那麼代碼以下:學習

class ZhangSan implements Visitor {
   @Override
   public void visit(Games games) {
       games.play();
   }

   @Override
   public void visit(Photos photos) {
       photos.watch();
   }
}

class LiSi implements Visitor {
   @Override
   public void visit(Games games) {
       games.play();
   }
   @Override
   public void visit(Photos photos) {
       photos.watch();
   }
}

class Games implements Computer {
   @Override
   public void accept(Visitor visitor) {
       visitor.visit(this);
   }

   public void play() {
       System.out.println("play lol");
   }
}

class Photos implements Computer {
   @Override
   public void accept(Visitor visitor) {
       visitor.visit(this);
   }
   
   public void watch() {
       System.out.println("watch scenery photo");
   }
}

最後咱們還須要定義一個結構對象角色,提供一個的接口並容許該訪問者進行訪問,它能夠對這些角色進行增長、修改或刪除等操做和遍歷。
代碼以下:測試

class ObjectStructure {

    private List<Computer> computers = new ArrayList<Computer>();

    public void action(Visitor visitor) {
        computers.forEach(c -> {
            c.accept(visitor);
        });
    }
    public void add(Computer computer) {
        computers.add(computer);
    }
}

編寫好以後,那麼咱們來進行測試。
測試代碼以下:

public static void main(String[] args) {
       // 建立一個結構對象
       ObjectStructure os = new ObjectStructure();
       // 給結構增長一個節點
       os.add(new Games());
       // 給結構增長一個節點
       os.add(new Photos());
       // 建立一個訪問者
       Visitor visitor = new ZhangSan();
       os.action(visitor);

}

輸出結果:

play lol
watch scenery photo

訪問者模式優勢:

擴展性好,能夠在不修改對象結構中的元素的狀況下,爲對象結構中的元素添加新的功能;
符合單一職責原則,經過訪問者將無關的行爲分離,使職責單一;

訪問者模式缺點:

違反了迪米特原則,由於具體元素對訪問者公佈細節;
違反了依賴倒置原則,依賴了具體類,沒有依賴抽象;
對象結構變化困難,若對象結構發生了改變,訪問者的接口和訪問者的實現也都要發生相應的改變;

使用場景:

對象結構中對象對應的類不多改變,但常常須要在此對象結構上定義新的操做;
須要對一個對象結構中的對象進行不少不一樣的而且不相關的操做,而須要避免讓這些操做"污染"這些對象的類,也不但願在增長新操做時修改這些類。

中介者模式

簡介

中介者模式(Mediator Pattern),定義了一箇中介對象來封裝一系列對象之間的交互關係。中介者使各個對象之間不須要顯式地相互引用,從而使耦合性下降,並且能夠獨立地改變它們之間的交互行爲,屬於行爲型模式。
其主要的目的是用來下降多個對象和類之間的通訊複雜性。

簡單的來講就是提供一個平臺。好比生活中咱們常常用到的聊天軟件QQ、微信羣,或者是上網購物的網站淘寶、京東,又或者是房產中介。可是不管是QQ羣,仍是房產中介,他們都是充當一箇中間平臺的做用,咱們能夠直接經過這個平臺獲得咱們想要的信息,避免了獨自獲取花費的成本。

中介者模式主要由這四個角色組成, 抽象中介者(Mediator)、具體中介者(ConcreteMediator)、 抽象同事類(Colleague)和具體同事類(ConcreteColleague) 。

  • 抽象中介者(Mediator): 定義了同事對象到中介者對象之間的接口。
  • 具體中介者(ConcreteMediator): 實現抽象中介者的方法,它須要知道全部的具體同事類,同時須要從具體的同事類那裏接收信息,而且向具體的同事類發送信息。
  • 抽象同事類(Colleague): 定義了中介者對象的接口,它只知道中介者而不知道其餘的同事對象。
  • 具體同事類(ConcreteColleague) : 每一個具體同事類都只須要知道本身的行爲便可,可是他們都須要認識中介者。

示例圖以下:
在這裏插入圖片描述

這裏爲了方便理解,咱們使用一個簡單的示例來加以說明。
xuwujing建立了一個Java的QQ羣,並邀請了不少人進來,其中張三也加進來了,進羣以後,你們開始互相打招呼進行交流。。。
那麼咱們即可以根據這個簡單的例子來使用中介者模式進行開發。
首先依舊定義一個抽象的中介者,就是QQ羣,能夠進行交流;而後再定義一個抽象的同事類,能夠談話。
那麼這個抽象類的代碼以下:

interface QQqun {
   void exchange(Person person,String message);
}

abstract class Person{
   protected String name;
   protected QQqun qun;  
   Person(String name,QQqun qun){
       this.name = name;
       this.qun = qun;
   }
}

定義好該抽象類以後,咱們再來定義具體的同事類,也就是xuwujing和張三,能夠進行交流。

那麼代碼以下:

class ZhangSan extends Person{

   ZhangSan(String name, QQqun qun) {
       super(name, qun);
   }
   
    void exchange(String message){
       qun.exchange(this,message);
   }
   
    void talk(String message){
       System.out.println(name +"說:" + message);
   }
}

class XuWuJing extends Person{

   XuWuJing(String name, QQqun qun) {
       super(name, qun);
   }
   
    void exchange(String message){
       qun.exchange(this,message);
   }
   
    void talk(String message){
       System.out.println(name +"迴應:" + message);
   }
}

最後再來定義具體中介者對象,這個QQ羣的具體實現。
代碼以下:

class JavaQQqun implements QQqun{
    private ZhangSan zs;
    private XuWuJing xwj;

    public ZhangSan getZs() {
        return zs;
    }

    public void setZs(ZhangSan zs) {
        this.zs = zs;
    }

    public XuWuJing getXwj() {
        return xwj;
    }


    public void setXwj(XuWuJing xwj) {
        this.xwj = xwj;
    }


    @Override
    public void exchange(Person person, String message) {
            if(zs.equals(person)){
                zs.talk(message);
            }else if(xwj.equals(person)){
                xwj.talk(message);
            }
    }
}

最後再來進行測試,定義好交流平臺以及須要交流的人員。
那麼測試代碼以下:

public static void main(String[] args) {
    JavaQQqun jq = new JavaQQqun();  
       ZhangSan zs = new ZhangSan("張三", jq);
       XuWuJing xwj = new XuWuJing("xuwujing", jq);
       jq.setZs(zs);
       jq.setXwj(xwj);      
       zs.exchange("你們好!我是張三!");
       xwj.exchange("歡迎你!張三!");

}

輸出結果:

張三說:你們好!我是張三
xuwujing迴應:歡迎你!張三!

中介者模式優勢:

靈活性高,由於將同事類進行了解耦,使其沒必要有關聯性;
下降了類的複雜度,將一對多轉化成了一對一;

中介者模式缺點:

中介者使用過多,會使系統變得複雜難以維護;

使用場景:

經過一箇中間類來封裝多個類中的行爲,而又不想生成太多的子類。

注意事項:

若不明確各個類的職責,那麼就不要進行使用!

和外觀模式、代理模式比較

中介者模式和外觀模式、代理模式比較相似,可是又有不一樣。
和外觀模式比較,中介者模式中,同事類必須依賴與中介者,中介者也知道同事類;可是外觀模式中,子系統是不須要知道外觀類的存在,而且子系統是能夠脫離外觀模式的。
和代理模式,代理模式的核心就是代理做用,主要仍是對原先的類進行擴展或增長控制,好比進行權限控制;而中介者模式主要目的是爲了減小對象以前的耦合,也就是同事類直接相互獨立,互不影響。

參考文章: https://www.cnblogs.com/chenssy/p/3348520.html

其它

音樂推薦

分享一首頗有節奏感的電音!

項目的代碼

java-study是本人在學習Java過程當中記錄的一些代碼,也包括以前博文中使用的代碼。若是感受不錯,但願順手給個start,固然若是有不足,也但願提出。
github地址: https://github.com/xuwujing/java-study

原創不易,若是感受不錯,但願給個推薦!您的支持是我寫做的最大動力! 版權聲明: 做者:虛無境 博客園出處:http://www.cnblogs.com/xuwujing CSDN出處:http://blog.csdn.net/qazwsxpcm  我的博客出處:http://www.panchengming.com

相關文章
相關標籤/搜索