設計模式之訪問者模式

這是我參與8月更文挑戰的第5天,活動詳情查看:8月更文挑戰java

歡迎來到今天的學習,今天咱們一塊兒來學習下訪問者代理模式。多嘮叨幾句,本月將會對java的設計模式精講,歡迎點擊頭像,關注個人專欄,我會持續更新,加油!面試

系列文章:設計模式

設計模式之單例模式markdown

設計模式之工廠模式網絡

設計模式之建造者模式數據結構

設計模式之代理模式dom

...持續更新中ide

話很少說,進入正題函數

訪問者模式

我的認爲該模式在實際開發中運用並非不少,可是一旦要用到了,那即是無可替代的。post

訪問者模式的原始定義是:訪問者模式是一種將數據操做和數據結構分離的設計模式。容許在運行時將一個或多個操做應用於一組對象,將操做與對象結構分離。

訪問者模式核心關注點是分離一組對象結構和對象的操做,對象結構能夠各不相同,但必須以某一個或一組操做做爲鏈接的中心點。換句話說,訪問者模式是以行爲(某一個操做)做爲擴展對象功能的出發點,在不改變已有類的功能的前提下進行批量擴展。

聽起來是否是很抽象,固然這是很官方,很專業的詞來解釋,這理解起來可能費點勁,可是我今天會用最通俗的的場景和代碼來幫助你理解和學習。(當你看完我下面的例子講解以後,你回來再看這段話,便想說SO DE SI NE)

下面來看張圖(圖片來源於網絡)

image.png

針對上圖咱們作一下介紹:

  • Visitor接口或者抽象類,定義了訪問者類型訪問的類型和行爲,它的參數就是被訪問的元素,它的方法個數理論上與元素的個數是同樣的,所以,訪問者模式要求元素的類型要穩定,若是常常添加、移除元素類,必然會致使頻繁地修改 Visitor 接口,若是出現這種狀況,則說明不適合使用訪問者模式。

注意這裏,若是常常添加、移除元素類,必然會致使頻繁地修改 Visitor 接口,若是出現這種狀況,則說明不適合使用訪問者模式,那樣便違背了迪米特法則與開放原則。

  • Element:元素接口或者抽象類,它定義了一個接受訪問者(accept)的方法,其意義是指每個元素都要能夠被訪問者訪問。

注意這裏,這裏能夠代指訪問者的入口,能夠理解成訪問者,從這個方法內去分別訪問不一樣的對象,不一樣的元素

  • ElementA、ElementB:具體的元素類,它提供接受訪問的具體實現,而這個具體的實現,一般狀況下是使用訪問者提供的訪問該元素類的方法

注意這裏,說通俗點,就是接口的實現類,此元素被訪問到徹底是根據調用者的參數來決定

  • ObjectStructure 定義當中所提到的對象結構,對象結構是一個抽象表述,它內部管理了元素集合,而且能夠迭代這些元素提供訪問者訪問。

注意這裏,咱們知道,實際工做當中,可能會有若干個元素類,那麼ObjectStructure即是管理這些元素類的。

若是你看到這裏仍是依然以爲很抽象,便看下面的代碼示例!

代碼示例

咱們想象這樣一種場景,面試官(CTO)和研發人員(技術總監面試技術開發),固然還有咱們的產品經理面試產品助理。研發人員對於CTO而言,CTO主要在乎面試者的技術經驗,而產品經理(CPO)在乎產品助理的產品的經驗

那麼問題來了,這二者的關注點是不同的。這就須要技術總監和產品經理(CPO)兩種職位進行不一樣的處理。訪問者模式此時能夠派上用場了。

//面試者
public abstract class Interviewers {
    
    //面試者姓名
    public String name;
    public int experience ;// 面試者經驗(暫時用工做年限做爲直接經驗)

    public Interviewers(String name) {
        this.name = name;
        experience = new Random().nextInt(10);
    }
    // 核心方法,接受Visitor的訪問
    public abstract void accept(Visitor visitor);
}

複製代碼

Interviewers 類定義了面試者基本信息及一個 accept 方法,accept 方法表示接受訪問者的訪問,由子類具體實現。Visitor 是個接口,傳入不一樣的實現類,可訪問不一樣的數據。下面看看技術開發工程師和產品助理的代碼:

// 工程師
public class Engineer extends Interviewers {

    public Engineer(String name) {
        super(name);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    // 工程師經驗值(爲代碼量)
    public int getCodeLines() {
        return new Random().nextInt(10 * 10000);
    }
}
複製代碼
//產品助理
public class Product extends Interviewers {

    public Product(String name) {
        super(name);
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    // 產品助理產品數量
    public int getProducts() {
        return new Random().nextInt(10);
    }
}
複製代碼

工程師是代碼數量,產品助理是產品數量,他們的職責不同,也就是由於差別性,才使得訪問模式可以發揮它的做用。Interviewers、Engineer、Product 3個類型就是對象結構,這些類型相對穩定,不會發生變化。

下面看看 Visitor 類型的定義, Visitor 聲明瞭兩個 visit 方法,分別是對工程師和經理對訪問函數,具體代碼以下:

public interface Visitor {

    // 訪問工程師類型
    void visit(Engineer engineer);

    // 產品助理類型
    void visit(Product product);
}
複製代碼

首先定義了一個 Visitor 接口,該接口有兩個 visit 函數,參數分別是 Engineer、Product,也就是說對於 Engineer、Product 的訪問會調用兩個不一樣的方法,以此達成區別對待、差別化處理。具體實現類爲 CTOVisitor、CPOVisitor類,具體代碼以下:

// CTO訪問者
public class CTOVisitor implements Visitor {
    @Override
    public void visit(Engineer engineer) {
        System.out.println("開發工程師: " + engineer.name + ", 年限和代碼量: " + engineer.getProducts);
    }

    @Override
    public void visit(Product product) {
        System.out.println("產品助理: " + product.name + ", KPI: " + manager.kpi +
                ", 新產品數量: " + product.getProducts());
    }
}
複製代碼

OK,到這裏就結束

相關文章
相關標籤/搜索