目录
1. 说明 2. 应用场景 3. 结构图 4. 构成 5. 优缺点
6. java示例 6.1 非状态模式 6.1.1 问题分析 6.1.2 接口类 6.1.2 实现类 6.1.3 客户端 6.1.4 结果截图
6.2 状态模式 6.2.1 抽象状态类 6.2.2 状态类 6.2.3 上下文类 6.2.4 上下文类
1. 说明
1.允许一个对象在其内部状态改变时改变它的行为。 2.对象看起来似乎修改了它的类。 3.对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
2. 应用场景
1.一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为。 2.一个操作中含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这使得开发者可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象独立变化。
3. 结构图
4. 构成
1.环境角色:Context(上下文)定义客户端感兴趣的接口;维护一个ConcreteState子类的实例,这个实例定义当前状态 2.抽象状态角色:State(状态)定义一个接口以封装与Context的一个特定状态相关的行为 3.具体状态角色:ConcreteState(具体状态子类)每个子类实现与Context的一个状态相关的行为
5. 优缺点
5.1 优点
1.将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。 2.允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
5.2 缺点
1.状态模式的使用必然会增加系统类和对象的个数。 2.状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 3.状态模式对"开闭原则"的支持并不太好。
6. java示例
6.1 非状态模式
6.1.1 问题分析
1.使用了大量的switch case这样的判断(if else也是一样),使程序的可阅读性变差 2.扩展性差,如果新加了一种状态,则需要修改判断逻辑
6.1.2 接口类
package com.learning.state.before;
/**
* 电梯接口
*/
public interface ILift {
//定义四个电梯状态的常量
/**
* 打开状态
*/
int OPENING_STATE = 1;
/**
* 关闭状态
*/
int CLOSING_STATE = 2;
/**
* 运行状态
*/
int RUNNING_STATE = 3;
/**
* 停止状态
*/
int STOPPING_STATE = 4;
//设置电梯状态的功能
void setState(int state);
//电梯操作功能
void open();
//电梯关闭功能
void close();
//电梯运行功能
void run();
//电梯停止功能
void stop();
}
6.1.2 实现类
package com.learning.state.before;
/**
* @Description 电梯类
**/
public class Lift implements ILift{
//当前电梯状态
private int state;
@Override
public void setState(int state) {
this.state = state;
}
@Override
public void open() {
switch(state){
//如果当前电梯状态是开启状态
case OPENING_STATE:
//什么都不做
break;
//如果当前电梯状态是关闭状态,打开电梯
case CLOSING_STATE:
System.out.println("电梯打开了");
// 设置当前电梯状态为开启状态
setState(OPENING_STATE);
break;
//如果当前电梯状态是运行状态
case RUNNING_STATE:
//什么都不做
break;
//如果当前电梯状态是开启状态,打开电梯
case STOPPING_STATE:
System.out.println("电梯打开了");
setState(OPENING_STATE);
break;
}
}
@Override
public void close() {
switch(this.state) {
case OPENING_STATE:
//只有开门状态可以关闭电梯门
System.out.println("电梯关门了");
//关门之后电梯就是关闭状态了
this.setState(CLOSING_STATE);
break;
case CLOSING_STATE:
//已经是关门状态,不能关门
//什么都不做
break;
case RUNNING_STATE:
//运行时电梯门是关着的,不能关门
//什么都不做
break;
case STOPPING_STATE:
//停止时电梯也是关着的,不能关门
//什么都不做
break;
}
}
@Override
public void run() {
switch(this.state) {
case OPENING_STATE:
//电梯不能开着门运行
break;
case CLOSING_STATE:
//门关了,可以运行了
System.out.println("电梯运行了");
//设置为运行状态
this.setState(RUNNING_STATE);
break;
case RUNNING_STATE:
//已经是运行状态了
break;
case STOPPING_STATE:
System.out.println("电梯运行了");
//设置为运行状态
this.setState(RUNNING_STATE);
break;
}
}
@Override
public void stop() {
switch(this.state) {
case OPENING_STATE:
// 开门的电梯已经是是停止的了(正常情况下)
break;
case CLOSING_STATE:
// 关门时才可以停止
System.out.println("电梯停止了");
this.setState(STOPPING_STATE);
break;
case RUNNING_STATE:
// 运行时当然可以停止了
System.out.println("电梯停止了");
this.setState(STOPPING_STATE);
break;
case STOPPING_STATE:
break;
}
}
}
6.1.3 客户端
package com.learning.state.before;
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
// 创建电梯对象
Lift lift = new Lift();
// 设置当前电梯的状态
lift.setState(ILift.OPENING_STATE);
// 打开
lift.open();
lift.close();
lift.run();
lift.stop();
}
}
6.1.4 结果截图
6.2 状态模式
6.2.1 抽象状态类
package com.learning.state.after;
/**
* 抽象状态类
*/
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();
}
6.2.2 状态类
package com.learning.state.after;
/**
* 开启状态类
*/
public class OpeningState extends LiftState {
// 当前状态要执行的方法
@Override
public void open() {
System.out.println("电梯开启");
}
@Override
public void close() {
// 修改状态
super.context.setLiftState(Context.CLOSING_STATE);
// 调用当前状态中的context中的close方法
super.context.close();
}
@Override
public void run() {
// 什么都不做
}
@Override
public void stop() {
// 什么都不做
}
}
package com.learning.state.after;
/**
* 运行状态类
*/
public class RunningState extends LiftState {
/**
* 运行的时候是不能开电梯门
*/
@Override
public void open() {
// 什么都不做
}
/**
* 运行状态的电梯,门不需要再关
*/
@Override
public void close() {
// 什么都不做
}
/**
* 运行状态下要实现的方法
*/
@Override
public void run() {
System.out.println("电梯正在运行");
}
/**
* 运行状态可以停止
*/
@Override
public void stop() {
super.context.setLiftState(Context.STOPPING_STATE);
super.context.stop();
}
}
package com.learning.state.after;
/**
* 停止状态类
*/
public class StoppingState extends LiftState {
/**
* 停止状态可以开门
*/
@Override
public void open() {
// 状态修改
super.context.setLiftState(Context.OPENING_STATE);
// 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作
super.context.getLiftState().open();
}
/**
* 可以关门,这个动作不归我执行
*/
@Override
public void close() {
// 状态修改
super.context.setLiftState(Context.CLOSING_STATE);
// 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作
super.context.getLiftState().close();
}
/**
* 停止后,可以再跑起来
*/
@Override
public void run() {
// 状态修改
super.context.setLiftState(Context.RUNNING_STATE);
// 动作委托为CloseState来执行,也就是委托给ClosingState子类执行这个动作
super.context.getLiftState().run();
}
/**
* 停止方法执行
*/
@Override
public void stop() {
System.out.println("电梯停止了");
}
}
package com.learning.state.after;
/**
* 关闭状态类
*/
public class ClosingState extends LiftState {
/**
* 电梯关闭状态可以再打开
*/
@Override
public void open() {
super.context.setLiftState(Context.OPENING_STATE);
super.context.open();
}
/**
* 电梯关闭状态实现的动作
*/
@Override
public void close() {
System.out.println("电梯门关闭");
}
/**
* 电梯关门之后启动
*/
@Override
public void run() {
super.context.setLiftState(Context.RUNNING_STATE);
super.context.run();
}
/**
* 电梯门关着,但没按楼层
*/
@Override
public void stop() {
super.context.setLiftState(Context.STOPPING_STATE);
super.context.stop();
}
}
6.2.3 上下文类
package com.learning.state.after;
public class Context {
// 定义对应状态对象的常量
public final static OpeningState OPENING_STATE = new OpeningState();
public final static ClosingState CLOSING_STATE = new ClosingState();
public final static RunningState RUNNING_STATE = new RunningState();
public final static StoppingState STOPPING_STATE = new StoppingState();
// 定义一个当前电梯状态变量
private LiftState liftState;
public LiftState getLiftState(){
return liftState;
}
public void setLiftState(LiftState liftState){
this.liftState = liftState;
// 设置当前状态对象中的Context对象
this.liftState.setContext(this);
}
public void open(){
this.liftState.open();
}
public void close(){
this.liftState.close();
}
public void run(){
this.liftState.run();
}
public void stop(){
this.liftState.stop();
}
}
6.2.4 上下文类
package com.learning.state.after;
/**
* 客户端类
*/
public class Client {
public static void main(String[] args) {
// 创建环境角色对象
Context context = new Context();
// 设置当前电梯状态
context.setLiftState(Context.CLOSING_STATE);
context.open();
context.close();
context.run();
context.stop();
}
}