天天看點

java設計模式-行為型模式-場景了解-第三篇

一、行為型模式

1. 模闆方法模式

1.1 介紹

定義:

定義一個操作中的算法架構,而将算法的一些步驟延遲到子類中,使得子類可以不改變該算法結構的情況下重定義該算法的某些特定步驟。

結構:

模闆方法模式包含以下主要角色:

抽象類(Abstract Class):負責給出一個算法的輪廓和骨架,它由一個模闆方法和若幹個基本方法構成;

模闆方法:定義了算法的骨架,按某種順序調用其包含的基本方法;

基本方法:是實作算法各個步驟的方法,是模闆方法的組成部分,基本方法有可以分為三種:

  • 抽象方法(Abstract Method):一個抽象方法由抽象類聲明、由其具體子類實作;
  • 具體方法(Contrete Method):一個具體方法由一個抽象類或具體類聲明并實作,其子類可以進行覆寫也可以直接繼承;
  • 鈎子方法(Hook Method):在抽象類中已經實作,包括用于判斷的邏輯方法和需要子類重寫的空方法兩種;

一般鈎子方法是用于判斷的邏輯方法,這類方法名一般為isXxx,傳回值類型為boolean類型。

具體子類(Conctete Class):實作抽象類中所定義的抽象方法和構造方法,它們是一個頂級邏輯的組成步驟;

類圖:
java設計模式-行為型模式-場景了解-第三篇
​優缺點:

優點:

  • 提高代碼複用性

将相同部分的代碼放在抽象的父類中,而将不同的代碼放入了不同的子類中。

  • 實作了反向控制

通過一個父類調用其子類的操作,通過對子類的具體實作擴充不同的行為,實作了反向控制,并符合”開閉原則“。

缺點:

  • 對每個不同的實作都需要定義一個子類,這會導緻類的個數增加,系統更加龐大,設計也更加抽象;
  • 父類中的抽象方法由子類實作,子類執行的結果會導緻父類的結果,這導緻一種反向的控制結構,它提高了代碼閱讀的難度;

1.2 适用場景

算法的整體步驟很固定,但其中個别部分易變時,這時候就可以使用模闆方法模式,将容易變的部分抽象出來,供子類實作。

需要通過子類來決定父類算法中某個步驟是否執行,實作子類對父類的反向控制JDK源碼解析。

InputStream類就使用了模闆方法模式,在InputStream類中定義了多個read()方法

public abstract int read() throws IOException;


    public int read(byte[] var1) throws IOException {
        return this.read(var1, 0, var1.length);
    }

    public int read(byte[] var1, int var2, int var3) throws IOException {
        if (var1 == null) {
            throw new NullPointerException();
        } else if (var2 >= 0 && var3 >= 0 && var3 <= var1.length - var2) {
            if (var3 == 0) {
                return 0;
            } else {
                int var4 = this.read();//調用了無參的read(),使用了反向控制,調用的是實作類
                if (var4 == -1) {
                    return -1;
                } else {
                    var1[var2] = (byte)var4;
                    int var5 = 1;


                    try {
                        while(var5 < var3) {
                            var4 = this.read();
                            if (var4 == -1) {
                                break;
                            }
                            var1[var2 + var5] = (byte)var4;
                            ++var5;
                        }
                    } catch (IOException var7) {
                    }
                    return var5;
                }
            }
        } else {
            throw new IndexOutOfBoundsException();
        }
    }      

2. 政策模式

2.1 介紹

定義:

該模式定義了一系列算法,并将每個算法封裝起來,使它們可以互相替換,且算法的變化不會影響使用算法的客戶,政策模式屬于對象行為模式,它通過對算法進行封裝,把使用算法的責任和算法的實作分割開來,并委托給不同的對象對這些算法進行管理。

結構:

政策模式的主要角色如下:

抽象政策(Strategy)類:這是一個抽象角色,通常由一個接口或抽象類實作,此角色給出所有的具體政策所需的接口;

具體政策(Concrete Strategy)類:實作了抽象政策定義的接口,提供具體的算法實作或行為;

環境(Context)類:持有一個政策類的引用,最終給用戶端調用;

類圖:
java設計模式-行為型模式-場景了解-第三篇
​優缺點:

優點:

  • 政策類之間可以自由切換

由于政策類都實作同一個接口,是以使它們之間可以自由切換。

  • 易于擴充

增加一個新的政策隻需要添加一個具體的政策類即可,基本不需要改變原有代碼,符合“開閉原則”;

避免使用多重條件選擇語句(if else),充分展現面向對象設計思想;

缺點:

  • 用戶端必須指定所有的政策類,并自行決定使用哪一個政策類;
  • 政策模式将造成産生很多政策類,可以通過使用享元模式在一定程度上減少對象的數量;

2.2 使用場景

  • 一個系統需要動态地在幾種算法中選擇一種時,可将每個算法封裝到政策中;
  • 一個類定義了多種行為,并且這些行為在這個類的操作中以多個條件語句的形式出現,可将每個條件分支移入它們各自的政策類中以代替這些條件語句;
  • 系統中各算法彼此完全獨立,且要求對客戶隐藏具體算法的實作細節時;
  • 系統要求使用算法的客戶不應該知道其操作的資料時,可使用政策模式來隐藏域算法相關的資料結構;
  • 多個類差別在表現行為不同,可以使用政策模式,在運作時動态選擇具體要執行的行為;

2.3 JDK源碼解析

Comparator中的政策模式。在Array類中有一個sort()方法

public static <T> void sort(T[] var0, Comparator<? super T> var1) {
        if (var1 == null) {
            sort(var0);
        } else if (Arrays.LegacyMergeSort.userRequested) {
            legacyMergeSort(var0, var1);
        } else {
            TimSort.sort(var0, 0, var0.length, var1, (Object[])null, 0, 0);
        }
    }      

參數Comparator<? super T>用到了政策模式,即實作那種具體的政策

3. 指令模式

3.1 介紹

定義:

将一個請求封裝為一個對象,使送出請求的責任和執行請求的責任分隔開,這樣兩者之間通過指令對象進行溝通,這樣友善将指令對象進行存儲、傳遞、調用、增加與管理。

結構:

指令模式包含以下主要角色:

  • 抽象指令類(Command)角色:定義指令的接口,聲明執行的方法;
  • 具體指令(Concrete Command)角色:具體的指令,實作指令接口;通常會持有接受者,并調用接受者的功能來完成指令要執行的操作;
  • 實作者/接受者(Receiver)角色:接受者,真正執行指令的對象,任何類都可能成為一個接受者,隻要它能夠實作指令要求實作的相應功能;
  • 調用者/請求者(Invoker)角色:要求指令對象執行請求,通常會持有指令對象,可以持有很多的指令對象,這個是用戶端真正觸發指令并要求指令執行相應操作的地方,也就是說相當于使用指令對象的入口;
類圖:
java設計模式-行為型模式-場景了解-第三篇
​優缺點:

​優點:

  • 降低系統的耦合度,指令模式能将調用操作的對象與實作該操作的對象解耦;
  • 增加或删除指令非常友善,采用指令模式增加與删除指令不會影響其他類,它滿足“開閉原則”,對擴充比較靈活;
  • 可以實作宏指令,指令模式可以與組合模式相結合,将多個指令裝配成一個組合指令,及宏指令;
  • 友善實作Undo和Redo操作,指令模式可以與後面介紹的備忘錄結合,實作指令的撤銷與恢複;

缺點:

  • 使用指令模式可能會導緻某些系統有過多的具體指令類;
  • 系統結構更加複雜;

3.2 使用場景

  • 系統需要将請求調用者和請求接收者解耦,使得調用者和接受者不直接互動;
  • 系統需要在不同的時間指定請求、将請求排隊和執行請求;
  • 系統需要支援指令的撤銷(Undo)和恢複(Redo)操作;

3.3 JDK源碼解析

Runable是一個典型指令模式,Runnable擔當指令的角色,Thread充當的是調用者,start方法就是其執行方法

/*指令接口(抽象指令角色)*/
public interface Runnable {
    void run();
}      
/*調用者*/
public class Thread implements Runnable {


   private Runnable target;


    public synchronized void start() {
        if (this.threadStatus != 0) {
            throw new IllegalThreadStateException();
        } else {
            this.group.add(this);
            boolean var1 = false;
            try {
                this.start0();
                var1 = true;
            } finally {
                try {
                    if (!var1) {
                        this.group.threadStartFailed(this);
                    }
                } catch (Throwable var8) {
                }
            }
        }
    }
//調用系統方法,開啟一個線程
  private native void start0();
  
    public void run() {
        if (this.target != null) {
            this.target.run();
        }
    }
}      

4. 責任鍊模式

4.1 介紹

定義:

又名職責鍊模式,為了避免請求發送者與多個請求處理者耦合在一起,将所有請求的處理者通過前一對象記住其下一個對象的引用而連成一條鍊,當有請求發生時,可将請求沿着這條鍊傳遞,直到有對象處理它為止。

結構:

職責鍊模式主要包含以下角色:

  • 抽象處理者(Handler)角色:定義一個處理請求的接口,包含抽象處理方法和一個後續連接配接;
  • 具體處理者(Contrete Handler)角色:實作抽象處理者的處理方法,判斷能否處理本次請求,如果可以處理請求則處理,否則将該請求轉發給他的後繼者;
  • 客戶類(Client)角色:建立處理鍊,并向鍊頭的具體處理者對象送出請求,它不關心處理細節和請求的傳遞過程;
類圖:
java設計模式-行為型模式-場景了解-第三篇
​優缺點:

優點:

  • 降低了對象之間的耦合度;
  • 該模式降低了請求發送者和接受者的耦合度;
  • 增強了系統的可擴充性;
  • 可以根據需要增加新的請求處理類,滿足開閉原則;
  • 增強了給對象指派職責的靈活性;
  • 當工作流程發送變化時,可以動态地改變鍊内的成員或者修改它們的次序,也可動态地新增或者删除責任;
  • 責任鍊簡化了對象之間的連接配接;
  • 一個對象隻需保持一個指向其後繼者的引用,不需保持其他所有處理者的引用,這避免了使用衆多的if或者if - else語句;
  • 責任分組;

每個類隻需要處理自己該處理的工作,不能處理的傳遞給下一個對象完成,明确各類的責任範圍,符合類的單一職責原則。

缺點:

  • 不能保證每個請求一定被處理,由于一個請求沒有明确的接收者,所有不能保證它一定會被處理,該請求可能一直傳到鍊的末端都得不到處理;
  • 對比較長的職責鍊,請求的處理可能涉及多個處理對象,系統性能将受到一定影響;
  • 職責鍊建立的合理性要靠用戶端來保證,增加了用戶端的複雜性,可能會由于職責鍊的錯誤設定而導緻系統出錯,如可能會造成循環調用;

4.2 源碼解析

在javaweb應用開發中,FilterChain是職責鍊(過濾器)模式的典型應用

Filter

public interface Filter {
    public void doFilter(Request request, Response response, FilterChain chain);
}      

Request

public interface Request {
}      

Response

public interface Response {
}      

FilterChain

public class FilterChain {

    private List<Filter> filters = new ArrayList<>();

    private int index = 0;

    public FilterChain addFilter(Filter filter){
        this.filters.add(filter);
        return this;
    }

    public void doFilter(Request request, Response response){
        if(index == filters.size()){
            return;
        }
        Filter filter = filters.get(index);
        index++;
        filter.doFilter(request, response, this);
    }
}      

FirstFilter

public class FirstFilter implements Filter {
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        System.out.println("過濾器1 前置處理");

        chain.doFilter(request, response);

        System.out.println("過濾器1 後置處理");
    }
}      

SecondFilter

public class SecondFilter implements Filter {
    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        System.out.println("過濾器2 前置處理");

        chain.doFilter(request, response);

        System.out.println("過濾器2 後置處理");
    }
}      

Client

public class Client {
    public static void main(String[] args) {
        Request req = null;
        Response res = null;

        FilterChain filterChain = new FilterChain();
        filterChain.addFilter(new FirstFilter()).addFilter(new SecondFilter());
        filterChain.doFilter(req,res);
    }
}      

5. 狀态模式

5.1 介紹

定義:

對于有狀态的對象,把複雜的“判斷邏輯”提取到不同的狀态對象中,允許狀态對象在其内部狀态發送改變時改變其行為。

結構:

狀态模式包含以下主要角色:

  • 環境(Context)角色:也稱為上下文,它定義了客戶程式需要的接口,維護一個目前狀态,并将與狀态相關的操作委托給目前狀态對象來處理;
  • 抽象狀态(State)角色:定義一個接口,用以封裝環境對象中的特定狀态所對應的行為;
  • 具體狀态(Concrete)角色:實作抽象狀态所對應的行為;
類圖1:
java設計模式-行為型模式-場景了解-第三篇
類圖2:
java設計模式-行為型模式-場景了解-第三篇
​優缺點:

優點:

  • 将所有與某個狀态有關的行為放到一個類中,并且可以友善地增加新的狀态,隻需要改變對象狀态即可改變對象的行為;
  • 允許狀态轉換邏輯與狀态對象合成一體,而不是某一個巨大的條件語句塊;

缺點:

  • 狀态模型的使用必然會增加系統類和對象的個數;
  • 狀态模型的結構與實作都較為複雜,如果使用不當将導緻程式結構和代碼的混亂;
  • 狀态模型對“開閉原則”的支援并不太好;

5.2 使用場景

  • 當一個對象的行為取決于它的狀态,并且它必須在運作時根據狀态改變它的行為時,就可以考慮使用狀态模型;
  • 一個操作中含有龐大的分支結構,并且這些分支決定于對象的狀态時;

6. 觀察者模式

6.1 介紹

定義:

又被稱為釋出-訂閱(Publish/Subscribe)模式,它定義了一種一對多的依賴關系,讓多個觀察者對象同時監視某一個主題對象,這個主題對象在狀态改變時,會通知所有觀察者對象,使他們能夠自動更新自己。

結構:

在觀察者模式中有如下角色:

Subject:抽象主題(抽象被觀察者),抽象主題角色把所有觀察者對象儲存在一個集合裡,每個主題都可以有任意數量的觀察者,抽象主題提供一個接口,可以增加和删除觀察者對象;

ConcreteSubject:具體主題(具體被觀察者),該角色将有關狀态存入具體觀察者對象,在具體主題的内部狀态發送改變時,給所有注冊過的觀察者發送通知;

Observe:抽象觀察者,是觀察者的抽象類,它定義了一個更新接口,使得在得到主題更換通知時更新自己;

ConcreteObserve:具體觀察者,實作抽象觀察者定義的更新接口,以便在得到主題更改通知時更新自身的狀态;

類圖:
java設計模式-行為型模式-場景了解-第三篇
優缺點:

優點:

  • 降低了目标與觀察者之間的耦合關系,兩者之間是抽象耦合關系;
  • 被觀察者發送通知,所有注冊的觀察者都會收到資訊(可以實作廣播機制);

缺點:

  • 如果觀察者非常多的話,那麼所有的觀察者收到被觀察者發送的通知會耗時;
  • 如果被觀察者有循環依賴的話,那麼被觀察者發送通知會使觀察者循環調用,會導緻系統奔潰;

6.2 使用場景

  • 對象間存在一對多關系,一個對象的狀态發送改變會影響其他對象;
  • 當一個抽象模型有兩個方面,其中一個方面依賴于另一個方面時;

6.3 JDK源碼

Observable類和Observer接口

案例:警察抓小偷

7. 中介者模式

7.1 介紹

定義:

又叫調停模式,定義一個中介角色來封裝一系列對象之間的互動,使原有對象之間的耦合松散,且可以獨立地改變它們之間的互動。

結構:

中介者模式包含以下角色:

抽象中介者(Mediator)角色:它是中介者的接口,提供了同僚對象注冊與轉發同僚對象資訊的抽象方法;

具體中介者(ConcreteMediator)角色:實作中介接口,定義一個List來管理同僚對象,協調各個同僚角色之間的互動關系,是以它依賴于同僚角色;

抽象同僚類(Colleague)角色:定義同僚類的接口,儲存中介者對象,提供同僚對象互動的抽象方法,實作所有互相影響的同僚類的公共功能;

具體同僚類(Concrete Colleague)角色:是抽象同僚類的實作者,當需要與其他同僚對象互動時,由中介者對象負責後續的互動;

類圖:
java設計模式-行為型模式-場景了解-第三篇
​優缺點:

優點:

  • 松散耦合

中介者模式通過把多個同僚之間的互動封裝到中介者對象裡面,進而使得同僚對象之間松散耦合,基本上可以做到互補依賴,這樣一來,同僚對象就可以獨立地變化和複用,而不再像以前那樣“牽一處而動全身”了。

  • 集中控制互動

多個同僚對象的互動,本封裝在中介對象裡面集中管理,使得這些互動行為發生改變的時候,隻需要改變中介者對象就可以了,當然如果是已經做好的系統,那麼擴充中介者對象,而各個同僚類不需要做修改。

  • 一對多關聯變為1對1關聯

沒有使用中介模式的時候,同僚對象之間的通常是一對多的,引入中介對象以後,中介者對象和同僚對象的關系通常變成雙向的一對一,這會讓對象的關系更容易了解和實作。

缺點:

當同僚類太多時,中介者的職責将很大,它會變得複雜而龐大,以至于系統難以維護。

7.2 使用場景

  • 系統中對象之間存在複雜的引用關系,系統結構混亂且難以了解;
  • 當想建立一個運作于多個類之間的對象,又不想生成新的子類時;

8. 疊代器模式

8.1 介紹

定義:

提供一個對象來順序通路聚合對象中的一系列資料,而不暴露聚合對象的内部表示。

結構:

疊代器模式主要包含以下角色:

抽象聚合(Aggregate)角色:定義存儲、添加、删除聚合元素以及建立疊代器對象的接口;

具體聚合(ConcreteAggregate)角色:實作抽象聚合類,傳回一個具體疊代器的執行個體;

抽象疊代器(Iterator)角色:定義通路和周遊聚合元素的接口,通常包括hasNext()、next()等方法;

具體疊代器(ConcreteIterator)角色:實作抽象疊代器接口中所定義的方法,完成對聚合對象的周遊,記錄周遊的目前位置;

類圖:
java設計模式-行為型模式-場景了解-第三篇
​優缺點:

優點:

  • 它支援不同的方式周遊一個聚合對象,在同一個聚合對象上可以定義多種周遊方式,在疊代器模式中隻需要用一個不同的疊代器來替換原有疊代器即可改變周遊算法,我們也可以自己定義疊代器的子類以支援新的周遊方式;
  • 疊代器簡化了聚合類,由于引入了疊代器,在原有的聚合對象中不需要再自行提供周遊等方法,這樣我們可以簡化聚合類的設計;
  • 在疊代器模式中,由于引入了抽象層,增加新的聚合類和疊代器類都很友善,無須修改原有代碼,滿足“開閉原則”的要求;

缺點:

  • 增加了類的個數,這在一定程度上增加了系統的複雜性。

8.2 使用場景

  • 當需要為聚合對象提供多種周遊方式時;
  • 當需要為周遊不同的聚合結構提供一個統計的接口時;
  • 當通路一個聚合對象的内容而無須暴露其内部細節的表示時;

8.3 JDK源碼:

List:抽象聚合類;

ArrayList:具體的聚合類;

Iterator:抽象疊代器;

List.iterator():傳回的是實作了Iterator接口的具體疊代器對象;

注意:

當我們在使用JAVA開發的時候,想要使用疊代器模式的話,隻要讓我們自己定義的容器類實作java.util.Iterable并實作其中的iterator()方法使其傳回一個java.util.Iterator的實作類就可以了

9. 通路者模式

9.1 介紹

定義:

封裝在一些作用于某種資料結構中的各元素的操作,它可以在不改變這個資料結構的前提下定義作用于這些元素的新的操作。

結構:

通路者模式包含以下主要角色:

  • 抽象通路者(Visitor)角色:定義了對每一個元素(Element)通路的行為,它的參數就是可以通路的元素,它的方法個數理論上來講與元素類個數(Element的實作類個數)是一樣的,從這點不難看出,通路者模式要求元素類的個數不能改變;
  • 具體通路者(ConcreteVisitor)角色:給出對每一個元素類通路時所産生的具體行為;
  • 抽象元素(Element)角色:定義了一個接受通路者的方法(accept),其意義是指,每一個元素都要可以被通路者通路;
  • 具體元素(ConcreteElement)角色:提供接受通路方法的具體實作,而這個具體的實作,通常情況下是使用通路中提供的通路該元素類的方法;
  • 對象結構(Object Structure)角色:定義當中所提到的對象結構,對象結構是一個抽象表述,具體點可以了解為一個具有容器性質或者符合對象特性的類,它會含有一組元素(Element),并且可以疊代這些元素,供通路者通路;
類圖:
java設計模式-行為型模式-場景了解-第三篇
​優缺點:

優點:

  • 擴充性好

在不修改對象結構中的元素的情況下,為對象結構中的元素添加新的功能。

  • 複用性好

通過通路者來定義整個對象結構通用的功能,進而提高複用程度。

  • 分離無關行為

通過通路者來分離無關的行為,把相關的行為封裝在一起,構成一個通路者,這樣每一個通路者的功能都比較單一。

缺點:

  • 對象結構變化很困難

在通路者模式中,沒增加一個新的元素類,都要在每一個具體通路者類中增加相應的具體操作,這違背了“開閉原則”。

  • 違反了依賴倒置原則

通路者模式依賴了具體類,而沒有依賴抽象。

9.2 使用場景

  • 對象結構相對穩定,但其操作算法經常變化的程式;
  • 對象結構中的對象要提供多種不同且不相關的操作,而且要避免讓這些操作的變化影響對象的結構;

10. 備忘錄模式

10.1 介紹

定義:

又叫快照模式,在不破壞封裝性的前提下,捕獲一個對象的内部狀态,并在該對象之外儲存這個狀态,以便以後當需要時能将該對象恢複到原先儲存的狀态。

結構:

發起人(Originator)角色:記錄目前時刻的内部狀态資訊,提供建立備忘錄和恢複備忘錄的功能,實作其他業務功能,它可以通路備忘錄裡的所有資訊;

備忘錄(Memento)角色:負責存儲發起人的内部狀态,在需要的時候提供這些内部狀态給發起人;

管理者(Caretaker)角色:對備忘錄進行管理,提供儲存與擷取備忘錄的功能,但其不能對備忘錄的内容進行通路與修改;

備忘錄有兩個等價的接口:

宅接口:管理者(Caretajer)對象:(和其他發起人對象之外的任何對象)看到的是備忘錄的宅接口(narror Interface),這個宅接口隻允許他把備忘錄對象傳給其他的對象

寬接口:與管理者看到的宅接口相反,發起人對象可以看到一個寬接(wideInterface),這個寬接口允許它讀取所有的資料,以便根據這些資料恢複這個發起人對象的内部狀态;

類圖:

白箱備忘錄

java設計模式-行為型模式-場景了解-第三篇

黑箱備忘錄

java設計模式-行為型模式-場景了解-第三篇
優缺點:

優點:

  • 提供了一種可以恢複狀态的機制,當使用者需要時能夠比較友善地将資料恢複到某個曆史的狀态
  • 實作了内部狀态的封裝,除了建立它的發起人之外,其他對象都不能通路這些狀态資訊
  • 簡化了發起人類,發起人不需要管理和儲存其内部狀态的各個備份,所有狀态資訊都儲存在備忘錄中,并由管理者進行管理,這符合單一職責原則

缺點:

  • 資源消耗大,如果要儲存的内部狀态資訊過多或者特點頻繁,将會占用比較大的記憶體資源。

10.2 使用場景

  • 需要儲存和恢複的場景,需要存檔功能;
  • 需要提供一個可復原操作的場景,如Word、記事本、Photoshop、idea等軟體在編輯時按ctrl + z組合鍵,還有資料庫中事務操作;

11. 解釋器模式

11.1 介紹

定義:

給定一個語言,定義它的文法表示,并定義一個解釋器,這個解釋器使用該辨別來解釋語言中的句子。

結構:

抽象表達式(Abstract Expression)角色:定義解釋器的接口,約定解釋器的解釋操作,主要包含解釋方法interpret();

終結符表達式(Termnal Expression)角色:是抽象表達式的子類,用來實作文法中與終結符相關的操作,文法中的每一個終結符都有一個具體終結表達式與之相對應;

非終結符表達式(Nonterminal Expression)角色:也是抽象表達式的子類,用來實作文法中與非終結符相關的操作,文法中的每條規則都對應于一個非終結符表達式;

環境(Context)角色:通常包含各個解釋器需要的資料或是公共的功能,一般用來傳遞所有解釋器共享的資料,後面的解釋器可以從這裡擷取這些值

用戶端(Client):主要任務是将需要分析的句子或表達式轉換成使用解釋器對象描述的抽象文法樹,然後調用解釋器的解釋方法,當然也可以通過環境角色間接通路解釋器的解釋方法;

類圖:
java設計模式-行為型模式-場景了解-第三篇
優點:
  • 易于改變和擴充文法

由于在解釋器模式中使用類來表示語言的文法規則,是以可以通過繼承等機制來改變或擴充文法,每一條文法規則都可以表示為一個類,是以可以友善地實作一個簡單的語言。

  • 實作文法較為容易

在抽象文法樹中每一個表達式節點類的實作方式都是相似的,這些類的代碼編寫都不會特别複雜。

  • 增加新的解釋表達式較為友善

如果使用者需要增加新的解釋表達式隻需要對應增加一個新的終結符表達式或非終結符表達式,原有表達式類代碼無需修改,符合“開閉原則”。

缺點:

  • 對于複雜文法難以維護

在解釋器模式中,每一天規則至少需要定義一個類,是以如果一個語言包含太多文法規則,類的個數會急劇增肌,導緻系統難以管理和維護。

  • 執行效率較低

由于在解釋器模式中使用了大量的循環和遞歸調用,是以在解釋器較為複雜的句子時其速度很慢,而且代碼調試過程也比較麻煩。

11.2 使用場景

  • 當語言的文法較為簡單,且執行效率不是關鍵問題時;
  • 當問題重複出現,且可以用一種簡單的語言來進行表達時;
  • 當一個語言需要解釋執行,并且語言中的句子可以表示為一個抽象文法樹的時候;
參考聲明:

設計模式參考了B主黑馬程式員:

​​https://www.bilibili.com/video/BV1Np4y1z7BU?spm_id_from=333.999.0.0​​​

繼續閱讀