状态设计模式20

一、定义

        官方定义:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类,(State Pattern)是设计模式的一种,属于行为模式。

        我的理解:当一个对象具有多种状态的时候,将这些状态抽取出来。每一种状态对应的是一种行为,执行相关的行为会导致状态的改变。比如订单的“未支付状态”,它执行“支付动作”后,订单的状态转变为了“已支付状态”。将这些状态抽取出来,独立成为类,好处是将状态的转变转移到了“状态类”中,避免了客户端调用环境中大量的if-else判断状态的语句。

        推荐经典文章:Java设计模式——状态模式(STATE PATTERN)

-----------------------------------------------------------------------------------------------------------------------------------------

        2018年12月07日新增:重构——以多态取代条件表达式(状态模式)

        状态设计模式是有一定难度的设计模式,当初在学习那个电梯例子的时候,还无法掌握状态设计模式的精髓。现在在学习《重构 改善既有代码的设计》这本书的时候,再次学习了状态设计模式。

        实际问题就是,一种事物,或者说一种对象,例如员工,职位情况非常复杂。员工可能升职,可能调换部门,所以他的薪资计算方式就有一定的灵活性与难度。如果强行使用策略设计模式,或者说使用switch case 语句来用薪资工厂,选择合适的计算公式,都无法消除选择此员工的薪资计算公式所编写的条件表达式,例如switch语句、if - then - else 语句。

        状态设计模式的精髓就是:当前对象持有抽象状态类型引用,将不同的状态设计为子类。为当前对象设置好相应的状态后,可将当前对象的相关功能方法委托给状态子类对象去做。例如,员工的职位类型有非常多种,那么就创建一个员工职位类型的抽象对象,并让员工类持有这个抽象职位类型的引用,再为这个抽象职位类型创建设值方法。接着,为抽象职位类型创建子类,并实现相关计算薪资的办法。最后,在员工对象中,将计算薪资的方法委托给接收到的职位状态类型对象。

二、优缺点

        1.避免了过多的switch-case 或者 if-else语句。

        2.符合开闭原则和单一职责原则。每个状态都是一个子类,要修改的话,只要修改某个子类。

        缺点是

        1.如果状态过多,会导致状态子类数量过多,系统复杂性变高。

三、经典代码 第一个例子

        一种状态对应的是一种行为。

        

package test;
//电梯
public class Lift {
	//开门状态常量
	public static final OpeningState OPENING_STATE = new OpeningState();
	
	//关门状态常量
	public static final CloseState CLOSE_STATE = new CloseState();
	
	//运行状态常量
	public static final RunningState RUNNING_STATE = new RunningState();
	
	//停止状态常量
	public static final StoppingState STOPPING_STATE = new StoppingState();
	
	//当前电梯的状态的引用
	private LiftState liftState;

	public LiftState getLiftState() {
		return liftState;
	}

	//在设置当前状态的时候,要指明这个状态是哪个电梯的状态。
	//当然,就是当前这个电梯对象
	public void setLiftState(LiftState liftState) {
		/**
		 * 电梯Lift 中  维护了当前的 电梯状态
		 * 具体的电梯状态要指明:当前的状态 ,你是“哪个电梯”的状态
		 * “哪个电梯”这里的话,就是当前的这个电梯对象
		 */
		liftState.setLift(this);
		this.liftState = liftState;
	}
	
	//电梯的行为,它对应的是一种状态,比如开门状态,那么电梯就是在开门中
	public void open(){
		this.liftState.open();
	}
	
	public void close(){
		this.liftState.close();
	}
	
	//电梯的行为,它对应的是一种状态,比如运行状态,那么电梯就是在运行中
	public void run(){
		this.liftState.run();
	}
	
	public void stop(){
		this.liftState.stop();
	}
	
	public static void main(String[] args) {
		Lift lift = new Lift();
		lift.setLiftState(CLOSE_STATE);
		lift.open();
		lift.close();
		lift.run();
		lift.open();
		
	}
	

}
package test;

//抽象电梯状态
public abstract class LiftState {
	protected Lift lift;//当前这个状态,它是哪个电梯的状态?因此维护了电梯的引用
	
	public abstract void open();
	
	public abstract void close();
	
	public abstract void run();
	
	public abstract void stop();

	public Lift getLift() {
		return lift;
	}

	public void setLift(Lift lift) {
		this.lift = lift;
	}
	
	
}
package test;
//开门状态
public class OpeningState extends LiftState{

	public void open() {
		System.out.println("正在开门");
		
	}
        //关门的行为会导致电梯的状态转为关闭状态,关闭状态又对应的是 关闭的具体动作
	public void close() {
		super.lift.setLiftState(Lift.CLOSE_STATE);
		super.lift.getLiftState().close();
		
	}

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

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

}

 

package test;

public class CloseState extends LiftState{

	public void open() {
		super.lift.setLiftState(Lift.OPENING_STATE);
		super.lift.getLiftState().open();
		
	}

	public void close() {
		System.out.println("正在关门");
		
	}

	public void run() {
		super.lift.setLiftState(Lift.RUNNING_STATE);
		super.lift.getLiftState().run();
		
	}

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

}

 

package test;

public class RunningState extends LiftState{

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

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

	public void run() {
		System.out.println("正在运行");
		
	}

	public void stop() {
		super.lift.setLiftState(Lift.STOPPING_STATE);
		super.lift.getLiftState().stop();
		
	}

}

 

package test;

public class StoppingState extends LiftState{

	public void open() {
		super.lift.setLiftState(Lift.OPENING_STATE);
		super.lift.getLiftState().open();
		
	}

	public void close() {
		super.lift.setLiftState(Lift.CLOSE_STATE);
		super.lift.getLiftState().close();
	}

	public void run() {
		super.lift.setLiftState(Lift.OPENING_STATE);
		super.lift.getLiftState().open();
	}

	public void stop() {
		System.out.println("正在停止");
		
	}

}

 

四、与策略模式的区别

        状态模式中的不同的状态,它们会在执行另外不同的状态对应的行为的时候,状态会有切换,因此各种状态之间存在联系。

        策略模式是根据相关的条件进行判断,从而选择相关的策略,不同策略之间没有联系。

 

分割线--------------------------------------------------------------------------------------------

下一篇:中介者设计模式21

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态发生改变时改变它的行为。该模式的核心思想是封装对象的状态,使得它对外部的影响最小化。状态模式常常被应用于需要按照状态决定行为的场合,比如状态机、游戏状态等。 在状态模式中,我们通常会定义一个抽象状态类(Abstract State)和若干个具体状态类(Concrete State),每个具体状态类表示对象在不同状态下的行为。同时,我们还需要定义一个环境类(Context),它包含了一个状态对象,负责状态的切换和行为的调用。 状态模式的优点包括: 1. 状态模式状态的处理分散在不同的状态类中,使得每个状态类只需处理自己状态下的行为,降低了代码的复杂度和耦合度。 2. 状态模式状态和行为分离,使得对象的状态可以在运行时动态改变,而不需要改变对象自身的结构。 3. 状态模式符合“开闭原则”,容易扩展和增加新的状态和行为。 但是,状态模式也存在一些缺点,包括: 1. 状态模式会导致类的数量增加,其中每个状态都需要一个具体状态类,这可能会导致类的爆炸。 2. 状态模式会增加代码的复杂度,尤其是当状态之间的转换比较复杂时。 总之,状态模式是一种非常有用的设计模式,它可以让对象状态的变化更加灵活和可控。但是,在实际应用过程中,我们需要权衡其优缺点,选择合适的使用场景和实现方式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小大宇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值