State模式(状态设计模式)

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");
}

}

···

原文地址:https://www.cnblogs.com/dgwblog/p/9880151.html

时间: 2024-10-11 23:38:36

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

Java设计模式(十) 备忘录模式 状态模式

(十九)备忘录模式 备忘录模式目的是保存一个对象的某个状态,在适当的时候恢复这个对象. class Memento{ private String value; public Memento(String value){ this.value = value; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } class Storage

State Design Pattern 状态设计模式

设置好内部状态,然后根据不同的函数作为行为模式,进行状态转换. 有点像Finite Automata算法,两者的思想是一样的. 会Finite Automata,那么这个设计模式就很容易了. #pragma once #include <stdlib.h> #include <math.h> #include <random> #include <time.h> enum STATES { FULLY_RENTED, WAITING, GOT_APPLICA

State状态设计模式

1.状态模式:改变对象的行为 一个用来改变类的(状态的)对象. 2:问题:当你自己实现 State 模式的时候就会碰到很多细节的问题,你必须根据自己的需要选择合适的实现方法, 比如用到的状态(State)是否要暴露给调用的客户,以及如何使状态发生变化 用于改变状态的机制可能很简单也可能很复杂-比如状态机(State Machine) 3.代理(Proxy)设计模式实际上是状态设计模式的一个特例 4.类图以及UML(astah/jude)下载地址 : http://pan.baidu.com/s/

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

主要参考<大话设计模式>和<设计模式:可复用面向对象软件的基础>两本书.本文介绍命令模式的实现. 问题出发点 在实际开发中,我们经常会遇到这种情况:一个对象有多种状态,在每一个状态下,都会有不同的行为.那么在代码中我们经常是这样实现的. 代码如下: typedef enum tagState { state0, state1, state2 }State; void Action(State actionState) { if (actionState == state0) { /

设计模式之State模式

State模式定义: 允许一个对象在状态改变是,改变它的行为.看起来对象似乎修改了它的类. 模式理解(个人): State模式主要解决的事在开发中时常遇到的根据不同状态需要进行不同的处理操作的问题,而这样的问题,大部分人会采用switch-case语句进行处理,这样会造成一个问题:分支过多,而且如果加入一个新的状态就需要对原来的代码进行编译.State模式采用了对这些不同的状态进行封装的方式处理这类问题,当状态改变的时候,进行处理然后在切换到另一种状态.也就是说,把状态的切换责任交给了具体的状态

Java 实现状态(State)模式

/** * @author stone */ public class WindowState { private String stateValue; public WindowState(String stateValue) { this.stateValue = stateValue; } public String getStateValue() { return stateValue; } public void setStateValue(String stateValue) { t

Java状态模式(State模式)

State的定义:不同的状态,不同的行为:或者说,每个状态有着相应的行为. 何时使用状态模式 State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了. 不只是根据状态,也有根据属性.如果某个对象的属性不同,对象的行为就不一样,这点在数据库系统中出现频率比较高,我们经常会在一个数据表的尾部,加上property属性含义的字段,用以标识记录中一些特殊

State Design Pattern 状态设计模式2

其实本设计模式可以实现一些像人工智能式的问答. 这个跟人回答问题差不多,根据不同的问题作出不同的回答,而且在不同的状态,也会作出不同的回答. 如果有大量的数据,那么就可以作出千变万化的问答效果来哦. #include <stdio.h> enum STATE { HUNGARY, EAT, FULL }; class State { STATE myState; public: State(STATE s = HUNGARY) : myState(s) { } void eat() { swi

State模式详解--设计模式(14)

State模式来源:         每个人.事物在不同的状态下会有不同表现(动作),而一个状态又会在不同的表现下转移到下一个不同的状态(State).最简单的一个生活中的例子就是:地铁入口处,如果你放入正确的地铁票,门就会打开让你通过.在出口处也是验票,如果正确你就可以ok,否则就不让你通过(如果你动作野蛮,或许会有报警(Alarm)). 有限状态自动机(FSM)也是一个典型的状态不同,对输入有不同的响应(状态转移).通常我们在实现这类系统会使用到很多的Switch/Case语句,Case某种