设计模式(Java)—State模式

在State模式中,用类来表示状态,以类来表示状态后,可以通过切换类来方便的改变对象的状态。

示例程序
金库警报系统:

  • 金库与警报中心相连
  • 金库里有警铃和正常通话用的电话
  • 金库里有时钟,监视着现在的时间
  • 白天的时间范围是9:00-16:59,晚上的时间范围是17:00-23:59和0:00-8:59
  • 金库只能白天使用
  • 白天使用金库的话,会在警报中心留下记录
  • 晚上使用金库的话,会在警报中心发送紧急事态通知
  • 任何时候都可以使用警铃
  • 使用警铃的话,会向警报中心发送紧急事态通知
  • 任何时候都可以使用电话(但晚上只有留言电话)
  • 白天使用电话的话,会呼叫警报中心
  • 晚上使用电话的话,会呼叫警报中心的留言电话

在这里插入图片描述

示例程序的类图
在这里插入图片描述

State接口
该接口是表示金库状态的接口,在State接口中定义了以下事件对应的接口API

  • 设置时间
  • 使用金库
  • 按下警铃
  • 正常通话
package State;

//状态类接口,声明抽象方法
public interface State {
	public abstract void doClock(Context context,int hour );
	public abstract void doUse(Context context);
	public abstract void doAlarm(Context context);
	public abstract void doPone(Context context);

}

DayState类
该类表示白天的状态,该类实现了State接口,因此它还实现了State接口中声明的所有方法。

package State;

//实现状态接口的类,实现了所有的抽象方法,在生成状态实例时,单例模式
public class DayState implements State {
	private static DayState singleton = new DayState();
	private DayState() {
		// TODO Auto-generated constructor stub
	}
	public static State getInstance(){
		return singleton;
	}
	//时间变化时,改变当前状态对象
	@Override
	public void doClock(Context context, int hour) {
		// TODO Auto-generated method stub
		if(hour<9||hour>=17){
			context.changeState(NightState.getInstance());
		}

	}

	@Override
	public void doUse(Context context) {
		// TODO Auto-generated method stub
		context.recordLog("使用金库(白天)");

	}

	@Override
	public void doAlarm(Context context) {
		// TODO Auto-generated method stub
		context.callSecurityCenter("按下警铃(白天)");

	}

	@Override
	public void doPone(Context context) {
		// TODO Auto-generated method stub
		context.callSecurityCenter("正常通话(白天)");

	}
	public String toString(){
		return "[白天]";
	}

}

NightState类
该类表示晚上的状态。

package State;

//实现状态接口的类,生成状态实例时使用了单例模式
public class NightState implements State{
	private static NightState singleton = new NightState();
	private NightState() {
		// TODO Auto-generated constructor stub
	}
	public static NightState getInstance(){
		return singleton;
	}
	//当状态变化时,改变当前状态
	@Override
	public void doClock(Context context, int hour) {
		// TODO Auto-generated method stub
		if(hour>=9&&hour<17){
			context.changeState(DayState.getInstance());
		}

	}

	@Override
	public void doUse(Context context) {
		// TODO Auto-generated method stub
		context.callSecurityCenter("紧急:晚上使用金库");

	}

	@Override
	public void doAlarm(Context context) {
		// TODO Auto-generated method stub
		context.callSecurityCenter("按下警铃(晚上)");

	}

	@Override
	public void doPone(Context context) {
		// TODO Auto-generated method stub
		context.recordLog("晚上的通话录音");
	}
	public String toString(){
		return "[晚上]";
	}
}

Context接口
该接口是负责管理状态和联系警报中心的接口

package State;

//执行中心接口,声明抽象方法
public interface Context {
	public abstract void setClock(int hour);
	public abstract void changeState(State nightState);
	public abstract void callSecurityCenter(String msg);
	public abstract void recordLog(String msg);
}

SafeFrame类
该类使用GUI实现警报系统界面,它实现了Context接口。

package State;

import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

//状态改变时执行的动作类
public class SafeFrame extends Frame implements ActionListener,Context {
	private TextField textClock = new TextField(60);
	private TextArea textScreen = new TextArea(10,60);
	private Button buttonUse = new Button("使用金库");
	private Button buttonAlarm = new Button("按下警铃");
	private Button buttonPhone = new Button("正常通话");
	private Button buttonExit = new Button("结束");
	
	private State state  = DayState.getInstance();
	
	public SafeFrame(String title) {
		// TODO Auto-generated constructor stub
		super(title);
		setBackground(Color.lightGray);
		setLayout(new BorderLayout());
		add(textClock, BorderLayout.NORTH);
		textClock.setEditable(false);
		add(textScreen, BorderLayout.CENTER);
		textScreen.setEditable(false);
		Panel panel = new Panel();
		panel.add(buttonUse);
		panel.add(buttonAlarm);
		panel.add(buttonPhone);
		panel.add(buttonExit);
		add(panel, BorderLayout.SOUTH);
		
		pack();
		show();
		//添加时间监听
		buttonUse.addActionListener(this);
		buttonAlarm.addActionListener(this);
		buttonPhone.addActionListener(this);
		buttonExit.addActionListener(this);
		
	}
	@Override
	public void setClock(int hour) {
		// TODO Auto-generated method stub
		String clockString = "现在的时间是";
		if(hour<10){
			clockString += "0"+hour+":00";
		}else {
			clockString += hour+":00";
		}
		System.out.println(clockString);
		textClock.setText(clockString);
		state.doClock(this, hour);
	}

	@Override
	public void changeState(State state) {
		// TODO Auto-generated method stub
		System.out.println("从"+this.state+"状态变为了"+state+"状态");
		this.state = state;

	}

	@Override
	public void callSecurityCenter(String msg) {
		// TODO Auto-generated method stub
		textScreen.append("call!"+msg+"\n");

	}

	@Override
	public void recordLog(String msg) {
		// TODO Auto-generated method stub
		textScreen.append("record..."+msg+"\n");

	}
	//事件被触发时判断是哪个 事件发生,根据不同的事件执行不同的动作
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		System.out.println(e.toString());
		if(e.getSource()==buttonUse){
			state.doUse(this);
		}else if (e.getSource()==buttonAlarm) {
			state.doAlarm(this);
		}else if (e.getSource()==buttonPhone) {
			state.doPone(this);
		}else {
			System.out.println("?");
		}
		
	}

}

Main类

package State;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SafeFrame safeFrame = new SafeFrame("State Sample");
		for(int hour=0;hour<24;hour++){
			safeFrame.setClock(hour);
		}
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO: handle exception
		}

	}

}

示例程序的时序图
在这里插入图片描述

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值