状态模式
定义:
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。状态模式是一种行为模式。
状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
类图:
适用场景:
1. 一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。
2. 一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。
角色
环境角色(Context): 即上下文对象,他可以拥有一些内部状态。一般持有一个抽象状态类。客户端直接调用的就是context对象。
抽象状态角色(Sate):定义一个接口,用以封装环境对象的一个特定状态所对应的行为。
具体状态角色(ConcreteState):实现了抽象状态接口,一个具体实现状态类都描述了一种Context的一个状态
要点
1. 状态模式允许一个对象基于内部状态而拥有不同的行为。
2. 和程序状态机不同,状态模式用类代表状态。
3. Context会将行为委托给当前状态对象。
4. 通过将每个状态封装进一个类,我们把以后需要做的任何改变局部化了。
5. 状态模式和策略模式有相同的类图,但是它们的意图不同。
6. 策略模式通常会用行为或算法来配置Context类。
7. 状态模式允许Context随着状态的改变而改变行为。
8. 状态转换可以由State类或context类控制。
9. 使用状态模式通常会导致设计中类的数目大量增加。
10. 状态类可以被多个Context实例共享。
优缺点:
优点:
1. 将不同的状态局部化,利于扩展。如果新加一种状态不需要修改context代码,直接增加一种状态和已有的状态关联即可。
2. 使得状态转换显示化
3. State对象可被共享。State对象代表独立的状态,可以被多个Context共享。
缺点:
1. 随着状态增加,系统中的类也会增加
2. 状态模式的结构与实现比较复杂,一环扣一环,使用不当容易出问题。
实例
Context:
public class Context {
private BaseState baseState; //持有一个状态
private Integer hour;
/** * 外部请求的方法,处理逻辑交由具体的状态来处理 */ public void doRequest() { this.baseState.handle(this); } |
BaseState:抽象状态接口
/** * Created by IntelliJ IDEA. * User: yingkuohao * Date: 13-9-29 * Time: 下午3:13 * CopyRight:360buy * Descrption: 定义baeState接口,子接口描述每一个具体的状态。 * 状态模式跟策略模式很像, * 从代码上看,都是把if-else转移到具体的类中来,避免业务逻辑增加或修改时带来的核心逻辑修改。 * 但是二者的用途是不一样的: * 状态模式主要是一些平行行为之间的转换。 * 策略模式主要是算法上的对等行为的挑选。 * * 解决的方法也不同: 状态模式,通常是自我控制状态的改变。 策略模式,由外部指定使用什么样的策略。 * To change this template use File | Settings | File Templates. */ public interface BaseState {
public void handle(Context context);
} |
MorningState:状态对象——早上
public class MorningState implements BaseState {
public void handle(Context context) {
//处理0-6点的状态,其他状态转到noonState if (context.getHour() <= 6 && context.getHour() >= 0) { System.out.println("good moring,一天好心情"); } else { context.setBaseState(new NoonState()); context.doRequest(); }
} } |
NoonState:状态对象——中午
public class NoonState implements BaseState { public void handle(Context context) { if (context.getHour() >=12 && context.getHour() < 18) { System.out.println("good noon!"); } else { context.setBaseState(new NightState()); context.doRequest(); } } } |
NightState:状态对象——晚上
public class NightState implements BaseState {
public void handle(Context context) { if (context.getHour() >= 18 && context.getHour() < 24) { System.out.println("good night!"); } } } |
Client:客户端对象
public class Client { public static void main(String args[]) { Context context = new Context(); context.setBaseState(new MorningState()); context.setHour(5); context.doRequest();
context.setHour(19); context.doRequest();
} } |
和其他模式的区别
状态模式非常容易与策略模式和责任链模式想混。下面说说异同
1. 策略模式
策略模式主要是在Client中组装策略对象,而状态模式中状态的跳转都是实现写好的,Client不需要知道具体的逻辑。
状态模式中,状态迁移是核心内容,而策略模式中,迁移与此毫无关系。
策略模式中允许一个客户选择或提供一种策略,而这种思想在状态模式中完全没有。
两者的用途也不一样:
状态模式主要是一些平行行为之间的转换;策略模式主要是算法上的对等行为的挑选。
解决的方法也不同:
状态模式,通常是自我控制状态的改变;策略模式是由外部指定使用什么样的策略。
状态模式主要用于封装内部的状态,策略模式主要用于封装算法族。
2. 责任链模式
相同:
都可以解决if分支过多
不同:
状态模式是一个对象(即Context)的内在状态发生改变,责任链是多个对象之间的改变。
状态模式是各个状态对象自己知道下一个处理的对象是谁。而责任链模式中的各个对象并不指定其下一个处理对象是谁,只是在客户端才设定。
通俗来理解:
State模式相当于if-else ,责任链相当于switch,不完全责任链相当于加break的switch,完全责任链相当于不加break的switch。
推荐:http://blog.csdn.net/hguisu/article/details/7557252