天天看點

設計模式(三)- 狀态模式

toc

#狀态模式

當一個對象的内在狀态改變時允許改變其行為,這個對象看起來像是改變了其類。

在平常開發自己也會遇到好多方法過長,裡面的判斷語句太多,導緻後續修改十分麻煩。今天看到狀态模式的介紹,覺得很受益。下面通過一段代碼錯誤的顯示一遍沒有使用狀态模式的代碼

public class Work {
    private int hour;
    private boolean finished;
    private boolean taskFinished;
    
    public void workProgram() {
        if (hour < 12) {
            System.out.println("current time: "+new Date() + "  working in the morning");
        } else if (hour < 13) {
            System.out.println("current time: "+new Date() + "  have a break!");
        } else if (hour < 17) {
            System.out.println("current time: "+new Date() + "  working in the afternoon");
        } else {
            if (finished) {
                System.out.println("current time: "+new Date() + " after work!");
            } else if (hour <12) {
                System.out.println("current time: "+new Date() + "  very hard!");
            }
        }
    }
    
}
從上述代碼中看出,當我要修改hour的判斷範圍,或者在各個判斷條件之後新增一些功能,都會使這段方法變得十分長,而且閱讀起來也比較繁瑣。
是以代碼過長了就有壞味道了。在面向對象的設計中也希望做到代碼的責任分解。           

複制

當一個對象狀态轉換的條件表達式過于複雜的時候,把狀态的判斷邏輯移到不同的一系列類當中,可以把複雜的判斷邏輯簡單化,這就是狀态模式的主要作用。但并不是所有有判斷的都要使用狀态模式,簡單的判斷邏輯就不需要了。

代碼改良

/**
 * 工作類 沒有了判斷語句
 */
public class Work {
    private int hour;

    private boolean finished;

    private boolean taskFinished;

    private State state;

    private State currentState;

    public Work() {
        currentState = new ForenoonState();

    }

    public void workProgram() {
        currentState.workProgram(this);
    }

    public int getHour() {
        return hour;
    }

    public void setHour(int hour) {
        this.hour = hour;
    }

    public boolean isFinished() {
        return finished;
    }

    public void setFinished(boolean finished) {
        this.finished = finished;
    }

    public boolean isTaskFinished() {
        return taskFinished;
    }

    public void setTaskFinished(boolean taskFinished) {
        this.taskFinished = taskFinished;
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.currentState = state;
    }
}

/**
 * morning
 */
public class ForenoonState extends State {
    public void workProgram(Work work) {
        if (work.getHour() < 12) {
            System.out.println("current time: "+new Date() + "  working in the morning");
        } else {
            work.setState(new NoonState());
        }
    }
}

/**
 * noon
 */
public class NoonState extends State {
    public void workProgram(Work work) {
        if (work.getHour() < 13) {
            System.out.println("current time: "+new Date() + "  have a break!");
        } else {
            work.setState(new AfternoonState());
        }
    }
}

/**
 * afternoon
 */
public class AfternoonState extends State {
    public void workProgram(Work work) {
        if (work.getHour() < 17) {
            System.out.println("current time: "+new Date() + "  working in the afternoon");
        } else {
            //todo .......
        }
    }
}

/**
 * Client
 */
public class Client {

    public static void main(String[] args) {
        Work work = new Work();
        work.setHour(12);
        work.workProgram();

        work.setHour(13);
        work.workProgram();
    }
}           

複制

設計模式(三)- 狀态模式

image.png

從上術代碼中,在用戶端代碼不需要做任何的修改,程式可以變得非常靈活,當程式還需要添加一個額外的工作狀态時,再添加一個其它狀态類的代碼,也不影響其它狀态類的代碼。