设计模式(二十)—状态模式
最后更新于:2022-04-01 16:26:36
**定义**:当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
## 一般模式
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d0a479.jpg)
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中状态,打开,运行,停止,关闭。他们之间存在着紧密的状态切换关系。例如:
人乘坐电梯,打开-->关闭--->运行--->停止。关闭电梯时,可能存在运行和停止。我们通过程序
来模拟这里的状态之间的转换。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-06_5755340d20824.jpg)
~~~
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();
}
}
~~~
**状态模式的优点:**
---|结构清晰
---|遵循设计原则
---|封装性非常好
**状态模式的缺点:**
---|环境角色中封装的角色子类太多。 不好管理。
**状态模式的使用场景**
---|行为随状态改变而改变的场景
---|条件、分支判断语句的替代者。