**定義**:當一個對象內在狀態改變時允許其改變行為,這個對象看起來像改變了其類。
## 一般模式

state:抽象狀態角色
---|接口或抽象類,負責對象狀態定義,并且封裝環境角色以實現狀態切換。
ConcreteState:具體狀態角色
---|每一個具體狀態必須完成兩個職責,本狀態的行為管理以及去想狀態處理,通俗的說,就是本狀態下要做的事情,
以及本狀態如何過渡到其他狀態。
Context環境角色
---|定義客戶端需要的接口,并且負責具體狀態的切換。
狀態類是通過context(環境角色)來實現裝之間的轉換的。
~~~
public class StateTest {
public static void main(String[] args) {
//提供一個環境角色
Context context = new Context();
//想讓執行狀態1的handle1方法
context.setCurrentState(new ConcreteState1());
//執行handle2方法
context.handle2();
}
}
/**
* 抽象狀態角色:
* 封裝環境角色,實現狀態的切換
* @author Administrator
*/
abstract class State{
//提供一個環境角色,共子類訪問
protected Context context;
public void setContext(Context context) {
this.context = context;
}
//抽像的行為1角色
public abstract void handle1();
//抽像的行為2角色
public abstract void handle2();
}
/**
* 負責具體狀態的切換
* @author Administrator
*
*/
class Context{
//里面封裝了所有的狀態方法
protected final static ConcreteState1 state1 = new ConcreteState1();
protected final static ConcreteState2 state2 = new ConcreteState2();
//設置當前狀態
private State currentState;
public State getCurrentState() {
return currentState;
}
public void setCurrentState(State currentState) {
this.currentState = currentState;
//設置環境角色
this.currentState.setContext(this);
}
//提供handle1方法
public void handle1(){
this.currentState.handle1();
}
//提供handle2方法
public void handle2(){
this.currentState.handle2();
}
}
/**
* 具體狀態類的實現類,
* 主要抽象方法的具體實現方式。
* @author Administrator
*/
class ConcreteState1 extends State{
@Override
public void handle1() {
System.out.println("我是實現類1,的具體實現方法1...");
}
@Override
public void handle2() {
System.out.println("我是實現類1,的具體實現方法2...");
//切換到ConcreteState2類的handle2方法,這里就相當于是狀態的切換
super.context.setCurrentState(Context.state2);
super.context.handle2();
}
}
/**
* 具體狀態類的實現類,
* 主要抽象方法的具體實現方式。
* @author Administrator
*/
class ConcreteState2 extends State{
@Override
public void handle1() {
System.out.println("我是實現類2,的具體實現方法1...");
super.context.setCurrentState(Context.state1);
super.context.handle1();
}
@Override
public void handle2() {
System.out.println("我是實現類2,的具體實現方法2...");
}
}
~~~
## 一個例子:
?一個電梯他有4中狀態,打開,運行,停止,關閉。他們之間存在著緊密的狀態切換關系。例如:
?人乘坐電梯,打開-->關閉--->運行--->停止。關閉電梯時,可能存在運行和停止。我們通過程序
?來模擬這里的狀態之間的轉換。

~~~
public class StateT {
public static void main(String[] args) {
//提供一個環境角色
LiftContext context = new LiftContext();
//設置環境角色,為打開狀態
context.setCurrentLift(new Closeing());
context.close();
context.run();
context.stop();
}
}
/**
* 抽象的裝填類角色
* 定義抽像的方法,封裝角色。
* @author Administrator
*/
abstract class ILift{
//定義一個環境角色,共子類調用
protected LiftContext context;
public LiftContext getContext(){
return this.context;
}
public void setContext(LiftContext context) {
this.context = context;
}
//電梯的打開狀態
public abstract void open();
//電梯的打開關閉
public abstract void close();
//電梯的打開運行
public abstract void run();
//電梯的打開停止
public abstract void stop();
}
/**
* 抽象狀態類的實現類
* @author Administrator
*/
class Openning extends ILift{
@Override
public void open() {
System.out.println("---電梯打開,請上去...或下去");
}
@Override
public void close() {
//狀態轉換
super.context.setCurrentLift(LiftContext.CLOSE);
//委托給關閉狀態的類來執行
super.context.close();
}
@Override
public void run() {
System.out.println("打開狀態--不能運行..");
}
@Override
public void stop() {
System.out.println("打開狀態--已經停止");
}
}
/**
* 抽象狀態類的實現類
* @author Administrator
*/
class Closeing extends ILift{
@Override
public void open() {
//切換為打開狀態
super.context.setCurrentLift(LiftContext.OPEN);
super.getContext().open();
}
@Override
public void close() {
System.out.println("電梯門關閉..");
}
@Override
public void run() {
super.context.setCurrentLift(LiftContext.RUN);
super.getContext().run();
}
@Override
public void stop() {
}
}
/**
* 抽象狀態類的實現類
* @author Administrator
*/
class Running extends ILift{
@Override
public void open() {
System.out.println("運行中--電梯不能打開..");
}
@Override
public void close() {
System.out.println("運行中--電梯已關閉..");
}
@Override
public void run() {
System.out.println("---電梯正在運行...");
}
@Override
public void stop() {
//運行狀態--->停止狀態
super.context.setCurrentLift(LiftContext.STOP);
super.getContext().stop();
}
}
/**
* 抽象狀態類的實現類
* @author Administrator
*/
class Stoping extends ILift{
@Override
public void open() {
//停止之后-->打開電梯門
super.context.setCurrentLift(LiftContext.OPEN);
super.getContext().open();
}
@Override
public void close() {
System.out.println("停止狀態--電梯還是關閉的..");
}
@Override
public void run() {
System.out.println("停止狀態--電梯沒有運行..");
}
@Override
public void stop() {
System.out.println("--電梯停止了..");
}
}
/**
* 環境角色,
* 用于轉換他們之間的狀態
* @author Administrator
*/
class LiftContext{
//封裝四種狀態類
protected static final Openning OPEN = new Openning();
protected static final Closeing CLOSE = new Closeing();
protected static final Running RUN = new Running();
protected static final Stoping STOP = new Stoping();
//提供一個狀態類
private ILift currentLift;
public ILift getCurrentLift() {
return currentLift;
}
public void setCurrentLift(ILift currentLift) {
this.currentLift = currentLift;
//設置環境角色
this.currentLift.setContext(this);
}
//提供四種狀態類的方法
public void open() {
this.currentLift.open();
}
//提供四種狀態類的方法
public void close() {
this.currentLift.close();
}
//提供四種狀態類的方法
public void run() {
this.currentLift.run();
}
//提供四種狀態類的方法
public void stop() {
this.currentLift.stop();
}
}
~~~
**狀態模式的優點:**
---|結構清晰
---|遵循設計原則
---|封裝性非常好
**狀態模式的缺點:**
---|環境角色中封裝的角色子類太多。 不好管理。
**狀態模式的使用場景**
---|行為隨狀態改變而改變的場景
---|條件、分支判斷語句的替代者。
- 前言
- 6大設計原則(一)---單一職責原則
- 6大設計原則(二)---里氏替換原則
- 6大設計原則(三)---依賴倒置原則
- 6大設計模式(四)----接口隔離原則
- 6大設計原則(五)---迪米特法則
- 6大設計原則(六)---開閉原則。
- 設計模式(一)---單例模式
- 設計模式(二)---工廠方法模式
- 設計模式(三)---抽象工廠模式
- 設計模式(四)---模板方法模式
- 設計模式(五)---建造者模式
- 設計模式(六)---代理模式
- 設計模式(七)---原型模式
- 設計模式(八)---中介者模式
- 設計模式(九)---命令模式
- 設計模式(十)---責任鏈模式
- 設計模式(十一)---裝飾模式
- 設計模式(十二)---策略模式
- 設計模式(十三)---適配器模式
- 設計模式(十四)---迭代器模式
- 設計模式(十五)---組合模式
- 設計模式(十六)---觀察者模式
- 設計模式(十七)---門面模式
- 設計模式(十八)---備忘錄模式
- 設計模式(十八)---訪問者模式
- 設計模式(二十)---狀態模式
- 設計模式(二十二)---享元模式
- 設計模式(二十三)---橋梁模式