概念
对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,允许状态对象在其内部状态发生改变时改变其行为。
结构
抽象状态角色:定义一个接口或抽象类,用来封装环境对象中的特定状态所对应的行为
具体状态角色:实现抽象状态所对应的行为
环境角色:定义了客户程序需要的方法,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理
示例
目标:以服务的启用、禁用为例。假定调用启动服务、禁用状态的方法时需要处理不同的业务逻辑,抽取出两个具体状态对象,当改变服务的状态后,调用具体状态对象中的处理逻辑方法(因上一次所发的开门、关门案例太过于被大众熟知,已被人使用,导致被公众号平台判定为抄袭,故删除,此篇重新举例)
抽象状态角色
package 设计模式.行为型模式.状态模式;
/**
* 状态:抽象状态角色
*/
public abstract class State {
/**
* 处理逻辑
*/
abstract void handleLogic();
}
具体状态角色一
package 设计模式.行为型模式.状态模式;
/**
* 启用状态:具体状态角色
*/
public class EnableState extends State {
/**
* 处理逻辑
*/
@Override
void handleLogic() {
System.out.println("启用服务");
}
}
具体状态角色二
package 设计模式.行为型模式.状态模式;
/**
* 禁用状态:具体状态角色
*/
public class DisableState extends State {
/**
* 处理逻辑
*/
@Override
void handleLogic() {
System.out.println("禁用服务");
}
}
环境角色
package 设计模式.行为型模式.状态模式;
/**
* 环境角色类
*/
public class Context {
/** 状态角色对象 */
private State state;
/**
* 设置状态
*/
void setSate(State state) {
this.state = state;
}
/**
* 执行逻辑
*/
void execute() {
this.state.handleLogic();
}
}
测试类
package 设计模式.行为型模式.状态模式;
/**
* 测试类
*/
public class Client {
public static void main(String[] args) {
// 创建环境角色
Context context = new Context();
// 设置启用状态
context.setSate(new EnableState());
// 执行逻辑:启用服务
context.execute();
// 设置禁用状态
context.setSate(new DisableState());
// 执行逻辑:禁用服务
context.execute();
}
}
优缺点
优点
1.将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变状态即可改变对象的行为
2.允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块
缺点
1.增加了系统类和对象的个数
2.结构与实现比较复杂
3.若将状态对象的创建放到环境角色中作为静态成员变量,则在新增状态时,需要修改状态角色代码,此时不符合“开闭原则”
应用场景
1.当一个对象的行为取决于它的状态,并且它必须在运行时候根据状态改变它的行为时,可以使用状态模式
2.一个操作中有庞大的分支结构,并且这些分支决定于对象的状态时,可以使用状态模式