前言
作者更有一系列设计模式文章(还在持续更新),图例丰富,少量代码,适合入门,系列文章见末尾跳转
一、状态模式定义
状态模式:提供一种一对多的转化设计,当对象状态发生转变时,能够动态修改对象功能,使得对象状态变更。
可以通过状态转化图的形式表示:
状态转化图:通过描绘系统的状态及引起系统状态转换的事件,来表示系统的行为。
- 此外状态转换图还指明了作为特定事件的结果系统将做哪些动作(例如,处理数据),因此状态转换图提供了行为建模机制。
- 在状态转换图中,每一个节点代表一个状态,其中双圈是终结状态。
以电梯状态变化为例子:
- 电梯在关闭时,可以运行电梯到达运行状态,也可以在运行前再次停止(刷新状态),也可以打开电梯门。
- 在开启时,不能直接运行,开启时只可能为停止下的开启,开门状态下可以关门。
- 停止状态(来自关门状态),可以开门,也可以运行。
- 运行状态,只能通过停止来转变状态
二、状态模式的结构
- State/StateA…:状态定义类,支持各个状态下的行为。
- Context: 状态保存类,保存当前状态信息,可以修改状态,运行当前状态下的行为。
class User{
public static void main(String[] args){
Context context=new Context();
context.setState(new StateA());
//当前在状态A
context.request("输出A状态的行为")
//当前执行的StateA的处理函数
context.setState(new StateB());
//修改为状态B
context.request("输出B状态的行为")
//当前执行的StateB的处理函数
}
}
按照上面电梯的例子,通过在状态内部函数执行时修改状态(为了简单只实现开关转换):
abstract class State{
protected Context context;//需要在状态中转换状态
public setContext(Context context){
this.context=context;
}
//定义开门
public abstract void opendor();
//定义关门
public abstract void closedor();
}
class OpenningState extends State{
@Override
public void opendor(){
System.out.println("已经是打开状态了");
}
@Override
public void closedor(){
System.out.println("正在关闭电梯");
//修改状态,在Context中用静态量来保存状态
super.context.setState(Context.closeingState);
}
}
class OpenningState extends State{
@Override
public void closedor(){
System.out.println("已经是关闭状态了");
}
@Override
public void opendor(){
System.out.println("正在打开电梯");
//修改状态,在Context中用静态量来保存状态
super.context.setState(Context.openningState);
}
}
class Context{
public final static OpenningState openningState=new OpenningState();
public final static CloseingState closeingState=new CloseingState();
private State state;
public State getSate(){
return state;
}
public void setState(State state){
this.state=state;
this.state.setContext(this);
}
public void opendor(){
state.opendor();
}
public void closedor(){
state.closedor();
}
}
public class Test{
public static void main(String[] arg){
Context context=new Context();
//设置初始状态为关闭
context.setState(Context.closeingState);
context.opendor();
//“正在打开电梯”
context.closedor();
//“正在关闭电梯”
}
}
Context中保存了当前状态,当前状态又记录了Context,方便在执行完状态转换的函数(比如在关闭时执行打开电梯,就是一次状态转换)时修改Context中保存的当前状态。
即Context执行了当前状态State子类的状态转换函数——函数中更新了Context的当前状态——此时Context的函数变为另一个状态的相应函数。
三、备忘录模式定义
备忘录模式:在对象之外保存对象内部状态,在对象被修改后,允许通过外部保存的状态恢复。
比如你正在写一篇博客,然后写到一半copy一份到备忘录上保存一下,之后快写完了就发生喜闻乐见的失误操作(完全删除+自动保存等或者奇妙消失)导致你的博客草稿全无…
然后你可以通过备忘录恢复一部分…这就是备忘录模式!!!
四、备忘录模式结构
- Originator: 需要备份的源对象,能够creatMemento()输出一个备份状态,通过restore(memento)恢复备份状态。
- Memento:需要保存的状态信息的集合,不一定要保存Originator全部信息,可以只需要一部分,String可以改为自定义的一个Originator的属性集合。
- Caretaker: 备份请求者和保存者,相当于用户(可以请求Originator获取一个备份,然后保存,向Originator输送备份信息)
public class Demo{
private static Originator o=new Originator();
private static Caretaker c=new Caretaker();
public static void main(String[] args){
o.setState("现在我是这个状态");
c.save(o.creatMemento());//c保存了o创建的状态信息
o.setState("现在我修改了状态");
o.restore(c.retrieve());//o获取了c保存的备份信息
//现在o是"现在我是这个状态"这个备份的状态。
五、总结和评价
状态模式和备忘录模式都是保存修改对象状态的行为型模式——
-
状态模式:面对对象状态修改较多,状态间变化较为频繁的设计需求,能够在状态内部实现状态转换,而不是一串if-else或者switch语句来控制状态,实现了状态责任的分割。
-
备忘录模式:应用于对象需要保存和恢复的情况,不是又对象自身负责自己的保存,而是输出一个状态类,让其他类来保存状态(可以同时保存多个状态)。
综上所述:
- 状态模式优点:
- 封装了状态转换规则
- 灵活、简洁:方便添加新状态,避免了复杂的控制语句块
- 减少了对象个数:状态对象可以实现复用(此时状态不能绑定环境对象)
- 备忘录模式优点:
- 实现了对象的备份和保存,支持了撤销操作等
- 缺点:
- 使用结构复杂,需要巧妙的逻辑设计(状态模式先画状态图),增加了类的数量
设计模式系列文章
系列文章:一、创建型模式——工厂模式
二、创建型模式——单例模式、原型模式
三、创建型模式——建造者模式
四、结构型模式——装饰者模式
五、结构型模式——代理、适配器模式
六、结构型模式——外观模式
七、结构型模式——组合模式、桥接模式、享元模式
八、行为型模式——观察者模式
九、行为型模式——迭代器模式
十、行为型模式——模板方法、策略方法模式
十一、行为型模式——命令模式
十二、行为型模式——责任链模式
十三、行为型模式——状态模式、备忘录模式
结尾
作者长期更新,如果觉得本文还算不错的话,请给我一个大大的赞!!!
如果非常赞同这篇文章,请关注我,持续了解更多精彩博文!!!
作者主攻Java Web方向,平时长期更新Java Web基础概念文章,以及算法和数据结构——【一日双题—见微知著】系列。同时设计模式系列也会尽快一月内完结