2

前情提要

在实际开发中,我们常常会出现以下的代码情况:

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

这种代码结构是不是很糟糕,如果未来又有一个新状态加入,则又要加入一个新的else if语句,如此往复,则会产生一个非常糟糕的代码结构体。

那么该如何优化这串代码呢?这里有两种方式:一种是使用责任链模式,一种是使用策略模式

我们先来看看责任链模式是如何优化这串代码的:

责任链模式

首先上UML类图:
图片描述

设计代码:

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("我在吃晚餐");
    }
}

主类实现:

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.handleMessage(lunchState);
        // 我要吃晚餐
        int dinnerState = 3;
        breakfast.handleMessage(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方法中专心处理请求的业务逻辑,做到了单一职责原则。子类的实现只要继承该抽象类即可,非常简单。


艾尔雪枫
25 声望5 粉丝

Change every day!