23种设计模式——状态模式

目录

状态(State)模式

适用场景

UML图

示例代码

优缺点

状态模式VS策略模式

实例:一天中的工作状态

应用:工作中的请假流程


状态(State)模式

本质:根据状态来分离和选择行为。状态驱动,由上下文负责

适用场景

当一个对象状态转换的条件表达式过于复杂时,把状态的转换逻辑移到表示不同状态的一系列类中,把复杂的逻辑简化。

当某一事物在不同的状态下有不同表现(动作),而一个状态又会在不同表现下转移到下一个不同状态时,使用大量的Switch–Case语句是不可取的。

状态模式应运而生,将依赖于对象状态的分支封装到独立的类中。它允许一个对象在其内部状态改变时改变它的行为,看起来对象似乎修改了它的类(但实际上是从一个类跳转到另一个类)

UML图

Context:拥有State的一个引用

State:依赖于Context

示例代码

一个接口或抽象类,封装与Context特定状态相关的行为

public abstract class State {
	public abstract void Handle(Context context); 

}

 Context类以及它的一个特定状态:拥有State类的一个对象(引用)

public class Context {
	private State state;

	public Context(State state) {
		super();
		this.state = state;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
		System.out.println(state.getClass().getName());
	}
	
	public void request() {
		state.Handle(this);
        //核心
	}

}

具体状态: 每个子类实现与Context的特定状态相关的一个行为 

public class ConcreteStateA extends State{

	@Override
	public void Handle(Context context) {
		context.setState(new ConcreteStateB());
        //传给B状态
	}
}
public class ConcreteStateB extends State{

	@Override
	public void Handle(Context context) {
		context.setState(new ConcreteStateA());
        //传给A状态
	}
	
}
public class Main {

	public static void main(String[] args) {
		Context c=new Context(new ConcreteStateA());
		c.request();
		c.request();
		c.request();
	}

}

第一个c.request():起初Context类中的this是ConcreteStateA,经过request中的Handle(this)传入ConcreteStateA的的Handle(),此处改变为ConcreteStateB

第二个c.request():是从B状态又变为A状态

优缺点

优点:

  • 将与特定状态相关的行为局部化,并且将不同状态的行为分割开来
  • 消除条件分支语句,把状态转移逻辑分布到State的子类,减少了相互间的依赖。
  • 显式化进行状态转换:为不同的状态引入独立的对象,使得状态的转换变得更加明确。而且状态对象可以保证上下文不会发生内部状态不一致的状况,因为上下文中只有一个变量来记录状态对象,只要为这一个变量赋值就可以了

缺点:

  • 逻辑分散化:状态逻辑分布到了State的很多子类中,很难看到整个状态逻辑,这也带来了代码的维护问题


状态模式VS策略模式

在这里插入图片描述

策略模式:定义了算法家族,分别封装起来,让他们之间可以相互转换

状态模式:当一个状态的内部状态改变时允许改变其行为,这个对象看起来改变了其类

  • 相似:都有Context类,都是给一个具有多个子类的父类实现Context的算法逻辑
  • 区别:从二者的UML图可以看出,状态模式中子类ContextState的函数中持有context,通过context可以调用Context中的方法。

实例:一天中的工作状态

public abstract class State {
	public abstract void play(Work w);
}
public class Work {
	private int hour;//时间
	private State state;//状态
	public static boolean finish;//工作完成标志
	
	public Work() {
		state=new MoringState();
	}
	public void play() {
		state.play(this);//核心
	}
	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}

	public int getHour() {
		return hour;
	}

	public void setHour(int hour) {
		this.hour = hour;
	}
	
}
public class MoringState extends State{

	@Override
	public void play(Work w) {
		if(w.getHour()<12)
			System.out.println(w.getHour()+":上午工作,精神百倍");
		else {
			w.setState(new AfternoonState());
			w.play();
		}
	}
}

public class AfternoonState extends State{

	@Override
	public void play(Work w) {
		if(w.getHour()<18)
			System.out.println(w.getHour()+":下午工作,精神还行");
		else {
			w.setState(new EveningState());
			w.play();
		}
	}
	
}

public class EveningState extends State{

	@Override
	public void play(Work w) {
		if(Work.finish) {
			w.setState(new RestState());
			w.play();
		}
		else if(w.getHour()>=22) {
			w.setState(new SleepState());
			w.play();
		}
		else{
			w.setState(new WorkedState());
			w.play();
		}
		
	}
}

public class RestState extends State{

	@Override
	public void play(Work w) {
		System.out.println(w.getHour()+":工作完成了,睡觉");
	}
}

public class WorkedState extends State{
	
	@Override
	public void play(Work w) {
		System.out.println(w.getHour()+":工作还没有完成,加班");
	}
}

public class SleepState extends State{

	@Override
	public void play(Work w) {
		System.out.println(w.getHour()+":很晚了,睡觉");
	}
}
package com.day;

public class Main {
	public static void main(String[] args) {
		Work w1=new Work();	
		w1.setHour(15);
		w1.play();
		w1.setHour(21);
		w1.play();
		//w1.setHour(23);
		//w1.play();
		//若仍用w1.setHour(设置的时间点<=之前状态的时间),得到的也还是之前的状态
		
		System.out.println("第二天:");
		Work w2=new Work();
		w2.finish=true;
		w2.setHour(20);
		w2.play();
	}
}

应用:工作中的请假流程

某人提出请假申请,先由项目经理审批,如果项目经理不同意,审批就直接结束
如项目经理同意,再看是否超过3天,如果三天以内,审批直接结束
否则,交给部门经理,部门经理审核后,无论是否同意,审批直接结束

public abstract class State {
	public abstract void play(Apply a);
}
package com.apply;

public class Apply {
	private boolean ok1=false;
	private boolean ok2=false;
	private int time=0;
	State state=null;
	
	public Apply() {
		state=new XmanagerState();//项目经理
	}
	
	public void play() {
		state.play(this);
	}
	
	public boolean isOk1() {
		return ok1;
	}
	public void setOk1(boolean ok1) {
		this.ok1 = ok1;
	}
	
	public boolean isOk2() {
		return ok2;
	}

	public void setOk2(boolean ok2) {
		this.ok2 = ok2;
	}

	public int getTime() {
		return time;
	}

	public void setTime(int time) {
		this.time = time;
	}

	public State getState() {
		return state;
	}
	public void setState(State state) {
		this.state = state;
	}
	
}
//项目经理
public class XmanagerState extends State{

	@Override
	public void play(Apply a) {
		if(a.isOk1()) {
			a.setState(new TimeState());
			a.play();
		}else {
			System.out.println("你的请假未被项目经理通过");
		}
	}
}

public class TimeState extends State{

	@Override
	public void play(Apply a) {
		if(a.getTime()<=3) {
			System.out.println("你的请假已被项目经理通过");
		}else {
			a.setState(new DmanagerState());
			a.play();
		}
	}
}

//部门经理
public class DmanagerState extends State{

	@Override
	public void play(Apply a) {
		if(a.isOk2()) {
			System.out.println("你的请假已被部门经理通过");
		}else {
			System.out.println("你的请假未被部门经理通过");
		}
		
	}
}
public class Main {
	public static void main(String[] args) {
		Apply a1=new Apply();
		a1.setOk1(true);
		a1.setTime(5);
		a1.setOk2(false);
		a1.play();
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值