設計模式-狀態模式(State Pattern)
狀態模式是什麼?
允許一個物件再其類別狀態發生改變時改變它的行為,也就是說類的行為是基於它的狀態改變的。
狀態模式的要素
- 使用環境(context)角色:客戶程式是通過它來滿足自己的需求,它定義了客戶程式需要的介面,並且維護一個具體狀態角色例項。通過這個例項來決定當前的狀態。
- 狀態(state)角色:定義一個介面以封裝與使用環境角色的一個特定狀態相關的行為。
具體狀態角色(Concrete State):實現狀態角色定義的介面。
狀態模式適用的場景
1、行為隨狀態改變而改變的場景。 2、條件、分支語句的代替者(if—else,switch-case)。
簡單例子
package myDesignPatternsTest.statePattern.simpleDemo;
public class Context {
private State state;
public Context() {
state=null;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
}
package myDesignPatternsTest.statePattern.simpleDemo;
public interface State {
public void doAction(Context context);
}
package myDesignPatternsTest.statePattern.simpleDemo;
public class RunState implements State {
@Override
public void doAction(Context context) {
System.out.println("Player is in Run state");
context.setState(this);
}
@Override
public String toString() {
return "RunState{}";
}
}
package myDesignPatternsTest.statePattern.simpleDemo;
public class StopState implements State {
@Override
public void doAction(Context context) {
System.out.println("is stop state");
context.setState(this);
}
@Override
public String toString() {
return "stop";
}
}
package myDesignPatternsTest.statePattern.simpleDemo;
public class Client {
public static void main(String[] args) {
Context context=new Context();
RunState runState=new RunState();
runState.doAction(context);
System.out.println(context.getState());
StopState stopState=new StopState();
stopState.doAction(context);
System.out.println(context.getState());
}
}
這個簡單的例子沒什麼多講的。
複雜一點的例子
我們每天電梯執行的幾種狀態:開門,關門,執行,停止。
開門的時候:可以關門和停止
關門的時候:可以開門,執行,停止
執行的時候:只能停止
停止的時候:開門和執行
package myDesignPatternsTest.statePattern.diffDemo;
/**
* 定義電梯的狀態
*/
public abstract class LiftState {
//定義一個環境角色,也就是封裝狀態的變換引起的功能變化
protected Context context;
public void setContext(Context context) {
this.context = context;
}
public abstract void open();
public abstract void close();
public abstract void run();
public abstract void stop();
}
package myDesignPatternsTest.statePattern.diffDemo;
public class Context {
//定義出所有電梯的狀態
public static final OpenningState OPENNING_STATE=new OpenningState();
public static final ClosingState CLOSING_STATE=new ClosingState();
public static final RunningState RUNNING_STATE=new RunningState();
public static final StoppingState STOPPING_STATE=new StoppingState();
//定義一個當前電梯的狀態
private LiftState state;
public LiftState getState() {
return state;
}
public void setState(LiftState state) {
this.state = state;
//把當前電梯的狀態通知到各個實現類
this.state.setContext(this);
}
public void open(){
this.state.open();
}
public void close(){
this.state.close();
}
public void run(){
this.state.run();
}
public void stop() {
this.state.stop();
}
}
package myDesignPatternsTest.statePattern.diffDemo;
public class ClosingState extends LiftState {
//這個是關閉狀態該有的動作
public void close() {
System.out.println("電梯門關閉...");
}
//關閉後電梯是可以開門的
public void open() {
super.context.setState(Context.OPENNING_STATE);
super.context.open();
}
//關門後電梯是可以爬樓的
public void run() {
super.context.setState(Context.RUNNING_STATE);
super.context.run();
}
//關門了電梯也可能是停止執行了
public void stop() {
super.context.setState(Context.STOPPING_STATE);
super.context.stop();
}
}
package myDesignPatternsTest.statePattern.diffDemo;
public class OpenningState extends LiftState {
@Override
public void open() {
System.out.println("電梯的門是開著的");
}
//開了當然也能關了
public void close() {
super.context.setState(Context.CLOSING_STATE);
super.context.close();
}
//不可能開著跑
public void run() {
System.out.println("error:此人有病開著門跑");
}
//開門是時候一定是停止的
public void stop() {
}
}
package myDesignPatternsTest.statePattern.diffDemo;
public class RunningState extends LiftState{
//正在執行的時候開啟門?不存在
public void open() {
}
//跑的時候門一定是關閉的
public void close() {
}
@Override
public void run() {
System.out.println("電梯正在爬樓");
}
//能跑就能停
public void stop() {
super.context.setState(Context.STOPPING_STATE);
super.context.stop();
}
}
package myDesignPatternsTest.statePattern.diffDemo;
public class StoppingState extends LiftState {
@Override
public void open() {
super.context.setState(Context.OPENNING_STATE);
super.context.open();
}
//停止的時候門應該是關的
public void close() {
}
@Override
public void run() {
super.context.setState(Context.RUNNING_STATE);
super.context.run();
}
public void stop() {
System.out.println("現在電梯停止了");
}
}
package myDesignPatternsTest.statePattern.diffDemo;
public class Client {
public static void main(String[] args) {
Context context= new Context();
context.setState(new StoppingState());
context.open();
context.close();
context.run();
context.close();
context.stop();
}
}
電梯的門是開著的
電梯門關閉...
電梯正在爬樓
現在電梯停止了
Process finished with exit code 0
狀態模式的優缺點
優點: 1、封裝了轉換規則。 2、列舉可能的狀態,在列舉狀態之前需要確定狀態種類。 3、將所有與某個狀態有關的行為放到一個類中,並且可以方便地增加新的狀態,只需要改變物件狀態即可改變物件的行為。 4、允許狀態轉換邏輯與狀態物件合成一體,而不是某一個巨大的條件語句塊。 5、可以讓多個環境物件共享一個狀態物件,從而減少系統中物件的個數。
缺點: 1、狀態模式的使用必然會增加系統類和物件的個數。 2、狀態模式的結構與實現都較為複雜,如果使用不當將導致程式結構和程式碼的混亂。 3、狀態模式對"開閉原則"的支援並不太好,對於可以切換狀態的狀態模式,增加新的狀態類需要修改那些負責狀態轉換的原始碼,否則無法切換到新增狀態,而且修改某個狀態類的行為也需修改對應類的原始碼。
相關文章
- 設計模式之狀態模式---State Pattern設計模式
- JAVA設計模式之 狀態模式【State Pattern】Java設計模式
- 設計模式之策略模式和狀態模式(strategy pattern & state pattern)設計模式
- 狀態模式(State pattern)模式
- 設計模式之狀態模式(State)設計模式
- 設計模式——20狀態模式(State)設計模式
- 使用C# (.NET Core) 實現狀態設計模式 (State Pattern)C#設計模式
- C#設計模式系列:狀態模式(State)C#設計模式
- 設計模式--狀態模式State(行為型)設計模式
- 狀態模式(State)模式
- 【設計模式基礎】行為模式 - 8 -狀態(State)設計模式
- 23種設計模式 之 State模式(狀態模式)[C語言實現]設計模式C語言
- 轉載---Dephi狀態模式(State模式)模式
- 設計模式-狀態模式設計模式
- 設計模式:狀態模式設計模式
- 設計模式(十五)狀態模式設計模式
- 設計模式之——狀態模式設計模式
- javascript設計模式狀態模式JavaScript設計模式
- 設計模式(六):狀態模式設計模式
- PHP 設計模式之狀態模式PHP設計模式
- 簡說設計模式——狀態模式設計模式
- python設計模式狀態模式Python設計模式
- 設計模式20之狀態模式設計模式
- 極簡設計模式-狀態模式設計模式
- GoLang設計模式14 - 狀態模式Golang設計模式
- Python設計模式-狀態模式Python設計模式
- Java設計模式之狀態模式Java設計模式
- 設計模式系列之「狀態模式」設計模式
- .NET下的狀態(State)模式 ------行為型模式模式
- 詳解 state 狀態模式及在 C++ 設計模式程式設計中的使用例項C++設計模式程式設計
- 23種設計模式(七)-狀態設計模式設計模式
- 設計模式-策略模式(strategy pattern)設計模式
- 設計模式第八講-狀態模式設計模式
- 設計模式漫談之狀態模式設計模式
- python設計模式【9】-狀態模式Python設計模式
- 《Head First 設計模式》:狀態模式設計模式
- C#設計模式之狀態模式C#設計模式
- 設計模式系列9--狀態模式設計模式