1. 程式人生 > >設計模式(三)- 狀態模式

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

.get TP 導致 做到 ring bubuko 對象 狀態 一個

[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();
    }
}

技術分享圖片

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

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