状态模式——java设计模式(二十二)
程序员文章站
2024-03-23 08:31:52
...
简介
状态模式(State Pattern):允许一个对象在内部状态改变时改变行为,看起来似乎修改了类。
- 解决复杂对象的状态转换以及不同状态下行为的封装问题。状态模式可以将一个对象的状态提取出来封装到一个类中,使得对象状态变化更加灵活,并且客户端可以不用关心对象的当前状态和状态转换。
结构和实现
- 角色包括:
- 环境类:拥有多种状态的对象,维持一个状态对象的引用。
- 抽象状态类:声明各种状态的方法,并实现子类的相同方法。
- 具体状态类:实现抽象状态类,对应环境的一个具体状态,行为有所不同。
- 状态模式结构。
- 状态转换可以由环境类统一负责。新增具体状态需要修改环境类。
public void changeState() {
//判断属性值,根据属性值进行状态转换
if (value == 0) {
this.setState(new ConcreteStateA());
}
else if (value == 1) {
this.setState(new ConcreteStateB());
}
......
}
- 状态转换也可以由具体状态类负责。此时,状态类为了获得环境的属性,会依赖或关联环境类。
public void changeState(Context ctx) {
//根据环境对象中的属性值进行状态转换
if (ctx.getValue() == 1) {
ctx.setState(new ConcreteStateB());
}
else if (ctx.getValue() == 2) {
ctx.setState(new ConcreteStateC());
}
......
}
实例
状态类状态转换
- 银行账户存在3中状态,需要在其中转换。
- 余额>=0,正常,可存款和取款。
- -2000<余额<0,透支,可存款和取款,按天计算利息。
- 余额=-2000,受限,只能存款,按天计算利息
- 银行账户状态图。
- 银行账户结构图
- 账户初始为正常状态。
public Account(String owner,double init) {
this.owner = owner;
this.balance = balance;
this.state = new NormalState(this); //设置初始状态
}
- 调用存取款的函数之后,进行状态检查,判断是否需要转换状态。
public void deposit(double amount) {
acc.setBalance(acc.getBalance() + amount);
stateCheck();
}
环境类状态转换
- 开发放大镜,点击之后在1、2、4倍大小之间循环。
共享状态
- 对个环境对象需要共享一个或多个状态对象,需要将这个对象定义为环境类的静态变量,以便对象共享。
- 两个个开关共享开状态和关状态,需要同时开,系统才处于开的状态。
优缺点和适用范围
- 优点:
- 集中管理状态。状态转换的代码可封装在环境类和具体状态类的方法中,无需分散在业务代码里,使用庞大的条件语句。
- 易于改变行为。只需要改变具体状态类,可以方便的改变行为。
- 共享状态对象。减少系统中状态对象的个数。
- 缺点:
- 增加类和对象。提取出状态类和对象,增大开销。
- 结构复杂。状态模式结构和实现复杂,设计难度大。
- 不完全符合开闭原则。新增状态需要修改负责状态转换的源码,修改状态的行为也需要修改对应类的源码。
- 适用范围:
- 对象的行为依赖于状态。
- 代码中包含大量与对象状态相关的条件语句,使得代码的维护性和灵活性变差。
jdk中的应用
- Iterator中,根据迭代器的类型,具体操作不同。状态类为Iterator,具体状态类为各种集合的迭代器。
- 集合类的迭代器。
推荐阅读
-
Java设计模式(22)之中介者模式
-
状态模式——java设计模式(二十二)
-
设计模式——中介者模式
-
设计模式---中介者模式
-
支付过程中的设计模式-状态模式(一)
-
基于MVC设计模式实战ExtJS4.2高级组件+SSH2在线投稿系统
-
JBoss内置的HSQL DB数据库 JBossHSQLDBSQL Server设计模式JDBC
-
Struts2中的设计模式 -ThreadLocal模式 设计模式strutsthread多线程java
-
Struts2中的设计模式 -ThreadLocal模式 设计模式strutsthread多线程java
-
来自Jeff Dean的分布式系统设计模式(更新版) 设计模式应用服务器SilverlightMapreduceGoogle