State???

State模式中,我们用类来表示状态。以类来表示状态后,我们就能通过切换类来方便地改变对象的状态。当需要增加新的状态时,如何修改代码这个问题也会很明确。

  • 直接用状态代替硬编码

    依赖于状态的处理,来执行具体的操作

理清职责

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

名字=======》》》》》说明

State ||表示金库状态的接口

DayState ||表示“白天”状态的类。它实现了State接口

NightState ||表示“晚上”状态的类。它实现了State接口

Context ||表示管理金库状态,并与警报中心联系的接口

SafeFrame ||实现了Context接口。在它内部持有按钮和画面显示等UI信息

Main || 测试程序行为的类

  • 使用与不使用状态模式对比
  1. 不使用
使用金库时被调用的方法(){
if(白天){
向警报中心报告使用记录
]elseif(晚上){
向警报中心报告紧急事态
警铃响起时被调用的方法(){
向警报中心报告紧急事态
正常通话时被调用的方法(){
if(白天){
呼叫警报中心
}elseif(晚上){
呼叫警报中心的留言电话
}
  1. 使用
表示百天的状态的类{
使用金库时被调用的方法(){
向警报中心报告使用记录
警铃响起时被调用的方法(){
向警报中心报告紧急事态
正常通话时被调用的方法(){
呼叫警报中心
表示晚上的状态的类{
使用金库时被调用的方法(){
向警报中心报告紧急事态
警铃响起时被调用的方法(){
向警报中心报告紧急事态
正常通话时被调用的方法(){
呼叫警报中心的留言电话 - 相关设计模式 ◆Singleton模式(第5章)Singleton 模式常常会出现在ConcreteState角色中。在示例程序中,我们就使用了Singleton模式。这是因为在表示状态的类中并没有定义任何实例字段(即表示实例的状态的字段)。
◆Flyweight模式(第20章)在表示状态的类中并没有定义任何实例字段。因此,有时我们可以使用Flyweight模式在多个Context 角色之间共享ConcreteState角色。

UML

时序图:

Code

  • DayState \NightState State

public interface State { //设置时间
void doclock(Context context, int hour); // 使用金库
void doUse(Context context); // 按下警铃
void doAlarm(Context context); // 正常通话
void dophone(Context context); } public class NightState implements State { private NightState() {
} private static NightState singleton = new NightState(); public static State getInstance() {
return (State) singleton;
} @Override
public void doclock(Context context, int hour) {
if (hour >= 9 && hour < 17) {
context.changeState(DayState.getInstance());
}
} @Override
public void doUse(Context context) {
context.recordLog("使用金库[晚上]");
} @Override
public void doAlarm(Context context) {
context.callSecurityCenter("按下警铃[晚上]");
} @Override
public void dophone(Context context) {
context.recordLog("正常通话[晚上]");
} @Override
public String toString() {
return "DayState{晚上}";
} } public class DayState implements State { /**
* 这里使用单例模式,因为每次改变一次状态都会生成一次实例,非常浪费内存与时间
*/
private DayState() {
} private static DayState singleton = new DayState(); public static State getInstance() {
return singleton;
} @Override
public void doclock(Context context, int hour) {
if (hour < 9 || hour >= 17) {
context.changeState(NightState.getInstance());
} } @Override
public void doUse(Context context) {
context.recordLog("使用金库[白天]");
} @Override
public void doAlarm(Context context) {
context.callSecurityCenter("按下警铃[白天]");
} @Override
public void dophone(Context context) {
context.recordLog("正常通话[白天]");
} @Override
public String toString() {
return "DayState{白天}";
}
}
  • Context 、SateFrame 、MainT

···

public class MainT {

public static void main(String[] args) {
SateFrame frame = new SateFrame("Safe Smaple"); // 24个小时制
while (true){
for (int i = 0; i < 24; i++) {
frame.setClock(i);
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
} }
}
}

}

public interface Context {

//设置时间

void setClock(int hour);

// 改变状态
void changeState(State state); // 联系警报中心
void callSecurityCenter(String msg); // 在警报中心留下记录
void recordLog(String msg);

}

public class SateFrame 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 SateFrame(String title) throws HeadlessException {
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);
} /**
* 可以看出这里的操作就简化很多了:
* 基本只有业务逻辑代码:
* 判断状态相关的代码可以直接由相关的状态代码实现,
* 即为由类的状态代替了if else代码
*/ @Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==buttonUse){
state.doUse(this);
}else if(e.getSource()==buttonALarm){
state.doAlarm(this);
}else if(e.getSource()==buttonPhone){
state.dophone(this);
}else if(e.getSource()==buttonExit){
System.exit(0);
}else{
System.out.println("?");
}
} @Override
public void setClock(int hour) {
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) {
System.out.println("从"+this.state+"状态变为了"+state+"状态。");
this.state=state;
} @Override
public void callSecurityCenter(String msg) {
textScreen.append("调用---"+msg+"\n");
} @Override
public void recordLog(String msg) {
textScreen.append("记录---"+msg+"\n");
}

}

···

State模式(状态设计模式)的更多相关文章

  1. Java设计模式(19)状态模式(State模式)

    State的定义:不同的状态,不同的行为:或者说,每个状态有着相应的行为. 何时使用状态模式 State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If else ...

  2. java设计模式-State(状态)模式

    state定义     不同的状态,不同的行为;或者说,每个状态有着相应的行为.         就像电风扇的开关,一档的上一个是关闭,关闭的上一个是五档,五档的上一个是四档,以此类推,而且五档的下一 ...

  3. 设计模式之美:State(状态)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):由 ConcreteState 指定它的后继 State. 意图 允许一个对象在其内部状态改变时改变它的行为.对象看起来似乎修改 ...

  4. State状态设计模式

    1.状态模式:改变对象的行为 一个用来改变类的(状态的)对象. 2:问题:当你自己实现 State 模式的时候就会碰到很多细节的问题,你必须根据自己的需要选择合适的实现方法, 比如用到的状态(Stat ...

  5. State Pattern -- 状态模式原理及实现(C++)

    主要参考<大话设计模式>和<设计模式:可复用面向对象软件的基础>两本书.本文介绍命令模式的实现. 问题出发点 在实际开发中,我们经常会遇到这种情况:一个对象有多种状态,在每一个 ...

  6. STATE(状态)模式

    引子 场景 在我们软件开发的过程中,有许多对象是有状态的.而对象的行为会随着状态的改变而发生改变.例如开发一个电梯类,电梯有开门.关门.停止.运行等行为,同时电梯也会有开门状态.关门状态.停止状态.运 ...

  7. java设计模式-State模式

    1.背景: MM的状态是非常不固定的,说不定刚才还非常高兴,没准一会就生气了.就跟六月的天似的,说变就变. 封装一下MM的状态:smile,cry,say:MM的状态决定了这些方法该怎么执行.   2 ...

  8. java设计模式--行为型模式--状态模式

    什么是行为型模式,小编觉得就是对行为的一种描述啦,一种对某种行为模型的定义. 状态模式: 状态模式 概述 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被 ...

  9. 状态(State)模式

    状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改变其行为.这个对象看上去就像是改变了它的 ...

随机推荐

  1. vue2.0中的$router 和 $route的区别

    1.router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了 ...

  2. 洛谷【P1177】【模板】归并排序

    题目传送门:https://www.luogu.org/problemnew/show/P1177 归并排序: 1.先将\(a\)数组的区间\([l,mid],[mid+1,r]\)排成有序的. 2. ...

  3. 批量清除过期的binlog释放磁盘空间

    方案,总共24台db,一台台进去清理肯定不行,得需要写一个脚本,进行批量操作,方案思路大概如下 1,  建立双master列表masterlist; 一个master一行. 2,远程获取master ...

  4. webpy+nginx+uwsgi安装配置

    转:(1)安装Nginx1.1 下载nginx-1.0.5.tar.gz并解压1.2 ./configure (也可以增加--prefix= path指定安装路径)此时有可能会提示缺少pcre支持,如 ...

  5. Framework配置错误

    转自:http://blog.csdn.net/ked/article/details/25052955 VS2012命令提示符无法使用的解决方法 打开VS2012命令提示符时报错“ERROR: Ca ...

  6. [.net]手机APP与IIS服务器联调配置

    前端时间写过一段时间接口,在后期的时候,出现了一些无法通过查看日志来找出问题所在的bug.于是,将手机APP连接到IIS服务器上进行调试,下面是配置的具体步骤 1. 配置IIS  添加网站,将物理路径 ...

  7. 问题:HttpWebRequest request post 传参; 结果:好用的C# HttpWebRequest用Post同时提交参数和文件的封装类

    在项目中,本来都是在站内进行数据交互的,后来又加进来一个买的php网站(艹).需要进行数据交互,在没有考虑使用web服务的情况下,只有通过Post提交到页面进行数据交互是最好的方式了. 我这边使用的是 ...

  8. VIewPage+Fragment

    效果图: 代码 public class NewOrderListFargmentActivity extends BaseActivity implements OnClickListener { ...

  9. Debian安装Docker

    Debian 安装 Docker CE 准备工作 系统要求 Docker CE 支持以下版本的 Debian 操作系统: Stretch 9 Jessie 8 (LTS) Wheezy 7.7 (LT ...

  10. Java核心技术 卷1 基础知识-第一天

    基本数据类型 java是一种强数据类的的语言 共有8种基本数据类型 其中: 整型4种 int(4字节) short(2字节) long(8字节) byte(1字节) java中整型的范围与机器无关 长 ...