状态模式

“状态变化”模式

在组件构建过程中,某些对象的状态经常面临变化,通常要使用许多 if else 语句来判断对象的状态到底如何,然后才进行相对应的处理,这就使得代码不够优雅,如何对这些变化进行有效的管理?同时又维护高层模块的稳定?状态模式为这一问题提供了一种解决方案。

典型的模式:State,Memento

模式定义

允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了它的类。

2018年软件设计师下半年下午题正好有个例子可以帮助理解。

 

 会员的等级根据其里程数来变化

其中,

  • FrequentFly(Context上下文)定义客户感兴趣的接口;维护一个CState实例,这个实例定义当前的状态。
  • CState(状态)定义一个接口以封装与Context的一个特定状态相关的行为(travel)。
  • CSliver,CGold,CBasic(具体状态子类),每个实现与Context的一个状态相关的行为,即travel()。

先创建出 FrequentFlyContext 与 CState

package com.zlfan.state;

public abstract class CState {
	public int flyMiles; //里程数
	public abstract double travel(double miles,FrequentFlyerContext context);
}
package com.zlfan.state;

public class FrequentFlyerContext {
	
	CState state;
	double flyMiles;
	public FrequentFlyerContext(){
		state = new CNoCustomer();
		flyMiles = 0;
	}
	
	public void setState(CState state){
		this.state = state;
	}
	
	public void travel(double miles){
		double bonusMiles = state.travel(miles, this);
		flyMiles = flyMiles + bonusMiles;
	}

}

CState的4个子类,普卡会员,金卡会员,银卡会员,非会员

package com.zlfan.state;
/*
 * 普卡会员
 */
public class CBasic extends CState{

	@Override
	public double travel(double miles, FrequentFlyerContext context) {
		if(context.flyMiles>=25000 && context.flyMiles<50000)
			context.setState(new CSliver());
		if(context.flyMiles>=50000)
			context.setState(new CGold());			
		return miles;
	}

}
package com.zlfan.state;
/*
 * 金卡会员
 */
public class CGold extends CState{

	@Override
	public double travel(double miles, FrequentFlyerContext context) {
		if(context.flyMiles>=25000 && context.flyMiles<50000)
			context.setState(new CSliver());
		if(context.flyMiles<=25000)
			context.setState(new CBasic());
		return miles +0.5*miles;
	}

}
package com.zlfan.state;
/*
 * 银卡会员
 */
public class CSliver extends CState{

	@Override
	public double travel(double miles, FrequentFlyerContext context) {
		if(context.flyMiles>50000)
			context.setState(new CGold());
		if(context.flyMiles<=25000)
			context.setState(new CBasic());
		return miles + 0.25*miles;
	}

}
package com.zlfan.state;

/*
 * 非会员用户
 */
public class CNoCustomer extends CState{

	@Override
	public double travel(double miles, FrequentFlyerContext context) {
		System.out.println("您的里程数不会积累");
		return miles;
	}

}

对象如果改变状态,只要在FrequentFlyerContext类中设置当前的状态,就可以处理当前状态对应的操作travel(),无须再去判断状态情况,即上面的用户四个状态,直接设置就好了;如果不采用状态设计模式,我们就要为每一种状态(非会员,普卡,金卡,银卡)都要进行判断,这就是前面说的,代码有许多 if else 语句,不够优雅。

适用性

1.一个对象的行为决定于它的状态,并且它必须在运行时刻根据状态改变它的行为。

2.一个操作含有庞大的多分支的条件语句,且这些分支依赖于该对象的状态。这个状态常用一个或多个枚举常量表示。通常,有多个操作包含这一相同的条件结构。State模式将每一个条件分支放入一个独立的类中。这是的开发者可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象独立变化。

优缺点:

优点:结构清晰,符合开闭原则

缺点:使用大量的状态类

总结

  • State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象切换状态时,切换相应对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。
  • 为不同的状态引入不同的对象使得状态转变变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的。
  • 如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值