從實踐學習設計模式——優化多if代碼結構

前情提要

在實際開發中,咱們經常會出現如下的代碼狀況:java

if (state == 1){
            haveBreakfast();
        } else if (state == 2){
            haveLunch();
        } else if (state == 3){
            haveDinner();
        }

這種代碼結構是否是很糟糕,若是將來又有一個新狀態加入,則又要加入一個新的else if語句,如此往復,則會產生一個很是糟糕的代碼結構體。設計模式

那麼該如何優化這串代碼呢?這裏有兩種方式:一種是使用責任鏈模式,一種是使用策略模式優化

咱們先來看看責任鏈模式是如何優化這串代碼的:this

責任鏈模式

首先上UML類圖:
圖片描述spa

設計代碼:設計

public abstract class Handler {
    private Handler nextHandler;
    private int state;
    
    public Handler(int state) {
        this.state = state;
    }

    // 處理請求傳遞,注意final,子類不可重寫
    public final void handleMessage(int state) {
    // 傳遞狀態是否符合,不符合走下一級
        if (this.state == state) {
            this.report();
        } else {
            if (this.nextHandler != null) {
                // 交給下級處理
                this.nextHandler.handleMessage(demand);
            } else {
                System.out.println("沒有下級可處理");
            }
        }
    }

    public void setNextHandler(Handler handler) {
        this.nextHandler = handler;
    }

    // 抽象方法,子類實現
    // 這裏也用了模板方法設計模式
    public abstract void report();
}

public class HaveBreakfast extends Hanlder {
    public HaveBreakfast(){
        super(1);
    }
    
    public void report(){
        System.out.println("我在吃早餐");
    }
}

public class HaveLunch extends Hanlder {
    public HaveLunch(){
        super(2);
    }
    
    public void report(){
        System.out.println("我在吃中餐");
    }
}

public class HaveDinner extends Hanlder {
    public HaveDinner(){
        super(3);
    }
    
    public void report(){
        System.out.println("我在吃晚餐");
    }
}

主類實現:code

public class Client {
    public static void main(String[] args) {
        // 初始化
        HaveBreakfast breakfast = new HaveBreakfast();
        HaveLunch lunch = new HaveLunch();
        HaveDinner dinner = new HaveDinner();
        
        // 設置下一級
        lunch.setNextHandler(dinner);
        breakfast.setNextHandler(lunch);
        
        // 我要吃中餐
        int lunchState = 2;
        breakfast.report(lunchState);
        // 我要吃晚餐
        int dinnerState = 3;
        breakfast.report(dinnerState);
    }
}

用責任鏈模式實現了代碼的解耦,之後只要根據state值的不一樣,調用breakfast.report(state)便可。繼承

策略模式

一樣上UML類圖:
圖片描述圖片

設計代碼:開發

public interface Strategy {
    public void algorithm();
}

public class HaveBreakfast implements Strategy{

    public void algorithm() {
        System.out.println("我在吃早餐");
    }
    
}

public class HaveLunch implements Strategy{

    public void algorithm() {
        System.out.println("我在吃中餐");
    }
    
}

public class HaveDinner implements Strategy{

    public void algorithm() {
        System.out.println("我在吃晚餐");
    }
    
}

public class Context implements Strategy{
    private Strategy strategy;
    private final Map<Integer, Strategy> map = new HashMap<>();
    
    public void setStrategy(int state) {
        initMap();
        this.Strategy = this.map.get(state);
    }
    
    private void initMap() {
        this.map.put(1, new HaveBreakfast());
        this.map.put(2, new HaveLunch());
        this.map.put(3, new HaveDinner());
    }
    
    public void algorithm() {
        this.strategy.algorithm();
    }
}

實現代碼:

public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        // 我要吃中餐
        int lunchState = 2;
        context.setStrategy(lunchState);
        context.algorithm();
        // 我要吃晚餐
        int dinnerState = 3;
        context.setStrategy(dinnerState);
        context.algorithm();
    }
}

用策略模式也一樣實現了代碼的解耦。

策略模式 VS 責任鏈模式

經過以上分析,咱們知道使用責任鏈模式和策略模式都能解耦雜亂的if-else代碼,但二者又有什麼不一樣,實際開發中咱們該選用那種?結論是責任鏈是一種鏈式結構的處理方式,是有層級性的,而策略模式並無層級關係,選用哪一種可根據開發需求進行定奪。

拓展——模板方法模式

回頭看看上面責任鏈模式的代碼,Handler抽象類中定義了幾個方法,一個是final修飾的handleMessage,一個是抽象方法report,還有一個是setNextHandler。這三個分別對應模板方法模式中的三個基本方法,分別是具體方法handleMessage(抽象類聲明並實現,子類不實現)、抽象方法report(抽象類聲明,子類必須實現)、鉤子方法setNextHandler(抽象類聲明並實現,子類可擴展)。這樣結合模板方法模式的好處在哪?首先加了handleMessage方法,把請求的傳遞判斷從子類中剝離出來,讓子類在report方法中專心處理請求的業務邏輯,作到了單一職責原則。子類的實現只要繼承該抽象類便可,很是簡單。

相關文章
相關標籤/搜索