设计模式---状态模式

1.概述

在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理。最直接的解决方案是将这些所有可能发生的情况全都考虑到。然后使用if... ellse语句来做状态判断来进行不同情况的处理。但是对复杂状态的判断就显得力不从心了。随着增加新的状态或者修改一个状体(if else(switch case)语句的增多或者修改)可能会引起很大的修改,而程序的可读性,扩展性也会变得很弱。维护也会很麻烦。那么我就考虑只修改自身状态的模式。

例子1:按钮来控制一个电梯的状态,一个电梯开们,关门,停,运行。每一种状态改变,都有可能要根据其他状态来更新处理。例如,开门状体,你不能在运行的时候开门,而是在电梯定下后才能开门。

例子2我们给一部手机打电话,就可能出现这几种情况:用户开机,用户关机,用户欠费停机,用户消户等。所以当我们拨打这个号码的时候:系统就要判断,该用户是否在开机且不忙状态,又或者是关机,欠费等状态。但不管是那种状态我们都应给出对应的处理操作。

2.问题

对象如何在每一种状态下表现出不同的行为

3.解决方案

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

在很多情况下,一个对象的行为取决于一个或多个动态变化的属性,这样的属性叫做状态,这样的对象叫做有状态的(stateful)对象,这样的对象状态是从事先定义好的一系列值中取出的。当一个这样的对象与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化。

4.适用性

在下面的两种情况下均可使用State模式:
if else(
switch case)语句,且这些分支依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

5.结构

6.模式的组成

环境类(Context:  定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
抽象状态类(State:  定义一个接口以封装与Context的一个特定状态相关的行为。
具体状态类(ConcreteState:  每一子类实现一个与Context的一个状态相关的行为。

7.效果

State模式有下面一些效果:
状态模式的优点:
1 ) 它将与特定状态相关的行为局部化,并且将不同状态的行为分割开来: State模式将所有与一个特定的状态相关的行为都放入一个对象中。因为所有与状态相关的代码都存在于某一个State子类中, 所以通过定义新的子类可以很容易的增加新的状态和转换。另一个方法是使用数据值定义内部状态并且让 Context操作来显式地检查这些数据。但这样将会使整个Context的实现中遍布看起来很相似的条件if else语句或switch case语句。增加一个新的状态可能需要改变若干个操作, 这就使得维护变得复杂了。State模式避免了这个问题, 但可能会引入另一个问题, 因为该模式将不同状态的行为分布在多个State子类中。这就增加了子类的数目,相对于单个类的实现来说不够紧凑。但是如果有许多状态时这样的分布实际上更好一些, 否则需要使用巨大的条件语句。正如很长的过程一样,巨大的条件语句是不受欢迎的。它们形成一大整块并且使得代码不够清晰,这又使得它们难以修改和扩展。 State模式提供了一个更好的方法来组织与特定状态相关的代码。决定状态转移的逻辑不在单块的 i fs w i t c h语句中, 而是分布在State子类之间。将每一个状态转换和动作封装到一个类中,就把着眼点从执行状态提高到整个对象的状态。这将使代码结构化并使其意图更加清晰。

2) 它使得状态转换显式化: 当一个对象仅以内部数据值来定义当前状态时 , 其状态仅表现为对一些变量的赋值,这不够明确。为不同的状态引入独立的对象使得转换变得更加明确。而且, State对象可保证Context不会发生内部状态不一致的情况,因为从 Context的角度看,状态转换是原子的只需重新绑定一个变量(ContextState对象变量),而无需为多个变量赋值

3) State对象可被共享如果State对象没有实例变量即它们表示的状态完全以它们的类型来编码那么各Context对象可以共享一个State对象。当状态以这种方式被共享时, 它们必然是没有内部状态, 只有行为的轻量级对象。

状态模式的缺点:
1)
状态模式的使用必然会增加系统类和对象的个数。
2)
状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

8.实现

我们用电梯的例子来说明:

简单地实现代码:

// 关门的状态 
public class CloseState extends LiftSate {
	// 转换为开门的状态
	@Override
	public void open() {
		// 给环境设置状态
		super.content.setLiftSate(Content.OPEN_STATE);
		// 调用该状态下的方法
		super.content.getLiftSate().open();
	}

	@Override
	public void close() {
		// TODO Auto-generated method stub
		System.out.println("电梯门关闭");

	}

	// 转换为运行状态
	@Override
	public void run() {
		super.content.setLiftSate(Content.RUN_STATE);
		super.content.getLiftSate().run();
	}

	// 转换为停止的状态
	@Override
	public void stop() {
		super.content.setLiftSate(Content.STOP_STATE);
		super.content.getLiftSate().stop();

	}

}

//开门状态
public class OpenState extends LiftSate {

	@Override
	public void open() {
		System.out.println("门开着");

	}

	// 可以转化为关门状态
	@Override
	public void close() {
		super.content.setLiftSate(Content.CLOSE_STATE);
		super.content.getLiftSate().close();

	}

	@Override
	public void run() {
		// TODO Auto-generated method stub

	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub

	}

}

// 运行状态
public class RunState extends LiftSate {

	@Override
	public void open() {
		// TODO Auto-generated method stub

	}

	@Override
	public void close() {
		// TODO Auto-generated method stub

	}

	@Override
	public void run() {
		System.out.println("运行中");

	}

	// 只能转换为停止状态
	@Override
	public void stop() {
		super.content.setLiftSate(Content.STOP_STATE);
		super.content.getLiftSate().stop();

	}

}

// 停止状态
public class StopState extends LiftSate {

	// 可以转为开门状态
	@Override
	public void open() {
		super.content.setLiftSate(Content.OPEN_STATE);
		super.content.getLiftSate().open();

	}

	@Override
	public void close() {
		// TODO Auto-generated method stub

	}

	// 可以转运行状态
	@Override
	public void run() {
		super.content.setLiftSate(Content.RUN_STATE);
		super.content.getLiftSate().run();

	}

	@Override
	public void stop() {
		System.out.println("停止le");

	}

}

// 定义一个环境类  环境包含所有的状态 和 状态的基类   并将他们耦合在一起 并可以随意的转换状态
public class Content {
	// 定义出所有电梯的状态 成员变量
	public final static OpenState OPEN_STATE = new OpenState();
	public final static CloseState CLOSE_STATE = new CloseState();
	public final static RunState RUN_STATE = new RunState();
	public final static StopState STOP_STATE = new StopState();

	// 电梯状态基类 可以get set set的时候传入不同状态的成员变量
	private LiftSate liftSate;

	public LiftSate getLiftSate() {
		return liftSate;
	}

	// 不同的状态之间可以项目的切换
	public void setLiftSate(LiftSate liftSate) {
		this.liftSate = liftSate;
		// 把当前的环境通知到各个实现类中
		this.liftSate.setContent(this);
	}

	// 定义所有的动作, 每个状态下只可以执行相应的动作
	public void open() {
		this.liftSate.open();
	}

	public void close() {
		this.liftSate.close();
	}

	public void run() {
		this.liftSate.run();
	}

	public void stop() {
		this.liftSate.stop();
	}

}

// 电梯的开门 关闭 停止 运行 4种状态
public class Client {

	public static void main(String[] args) {
		// 创建一个环境
		Content content = new Content();
		// 给定一个状态
		content.setLiftSate(Content.RUN_STATE);
		content.open();
		content.close();
		content.run();
		content.stop();
	}
}

// 所有状态的基类
public abstract class LiftSate {
	// 环境的属性 所有子类都可以获取到环境属性
	protected Content content;

	public void setContent(Content content) {
		this.content = content;
	}

	public abstract void open();

	public abstract void close();

	public abstract void run();

	public abstract void stop();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值