设计模式(三)- 状态模式

toc

#状态模式

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

在平常开发自己也会遇到好多方法过长,里面的判断语句太多,导致后续修改十分麻烦。今天看到状态模式的介绍,觉得很受益。下面通过一段代码错误的显示一遍没有使用状态模式的代码

public class Work {
    private int hour;
    private boolean finished;
    private boolean taskFinished;
    
    public void workProgram() {
        if (hour < 12) {
            System.out.println("current time: "+new Date() + "  working in the morning");
        } else if (hour < 13) {
            System.out.println("current time: "+new Date() + "  have a break!");
        } else if (hour < 17) {
            System.out.println("current time: "+new Date() + "  working in the afternoon");
        } else {
            if (finished) {
                System.out.println("current time: "+new Date() + " after work!");
            } else if (hour <12) {
                System.out.println("current time: "+new Date() + "  very hard!");
            }
        }
    }
    
}
从上述代码中看出,当我要修改hour的判断范围,或者在各个判断条件之后新增一些功能,都会使这段方法变得十分长,而且阅读起来也比较繁琐。
所以代码过长了就有坏味道了。在面向对象的设计中也希望做到代码的责任分解。

当一个对象状态转换的条件表达式过于复杂的时候,把状态的判断逻辑移到不同的一系列类当中,可以把复杂的判断逻辑简单化,这就是状态模式的主要作用。但并不是所有有判断的都要使用状态模式,简单的判断逻辑就不需要了。

代码改良

/**
 * 工作类 没有了判断语句
 */
public class Work {
    private int hour;

    private boolean finished;

    private boolean taskFinished;

    private State state;

    private State currentState;

    public Work() {
        currentState = new ForenoonState();

    }

    public void workProgram() {
        currentState.workProgram(this);
    }

    public int getHour() {
        return hour;
    }

    public void setHour(int hour) {
        this.hour = hour;
    }

    public boolean isFinished() {
        return finished;
    }

    public void setFinished(boolean finished) {
        this.finished = finished;
    }

    public boolean isTaskFinished() {
        return taskFinished;
    }

    public void setTaskFinished(boolean taskFinished) {
        this.taskFinished = taskFinished;
    }

    public State getState() {
        return state;
    }

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

/**
 * morning
 */
public class ForenoonState extends State {
    public void workProgram(Work work) {
        if (work.getHour() < 12) {
            System.out.println("current time: "+new Date() + "  working in the morning");
        } else {
            work.setState(new NoonState());
        }
    }
}

/**
 * noon
 */
public class NoonState extends State {
    public void workProgram(Work work) {
        if (work.getHour() < 13) {
            System.out.println("current time: "+new Date() + "  have a break!");
        } else {
            work.setState(new AfternoonState());
        }
    }
}

/**
 * afternoon
 */
public class AfternoonState extends State {
    public void workProgram(Work work) {
        if (work.getHour() < 17) {
            System.out.println("current time: "+new Date() + "  working in the afternoon");
        } else {
            //todo .......
        }
    }
}

/**
 * Client
 */
public class Client {

    public static void main(String[] args) {
        Work work = new Work();
        work.setHour(12);
        work.workProgram();

        work.setHour(13);
        work.workProgram();
    }
}
image.png

从上术代码中,在客户端代码不需要做任何的修改,程序可以变得非常灵活,当程序还需要添加一个额外的工作状态时,再添加一个其它状态类的代码,也不影响其它状态类的代码。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏不止是前端

从实现一个Promise说起

尽管工作中用了无数次Promise async await,但是在写下这篇文章之前,却不知道Promise背后发生了些什么,我一直以为的逻辑是先等待Promis...

1544
来自专栏开发与安全

预处理--》编译--》运行的区别

相信很多人懂这个问题,也很多人没想过,包括我,今天看书想到了就写下来。先看程序(抱歉在linux下没有找到舒服的可以复制terminal的工具,只好截图了,将就...

1967
来自专栏闪电gogogo的专栏

【数据结构(C语言版)系列三】 队列

队列是一种先进先出的线性表,它只允许在表的一端进行插入,而在另一端删除元素。这和我们日常生活中的排队是一致的,最早进入队列的元素最早离开。在队列中,允许插入的一...

2432
来自专栏柠檬先生

Less 常用基础知识

LESS 中的注释   也可以额使用css 中的注释(/**/) 这种方式是可以被编译出来的。   也可以使用// 注释 不会被编译的 变量 ...

2076
来自专栏博岩Java大讲堂

Java虚拟机--对象的访问

3779
来自专栏守望轩

c#的细节(二)-修饰符

写在最前面的话: 《c#的细节》是我当初学习c#时候,做的一些学习笔记的整理,现在回头看来这些都是非常浅显的知识,是c#非常细节的地方,同时也是不能忽略的...

1797
来自专栏刘君君

JVM Specification notes 1 -Jvm Structure

摘要: Jvm Structure 正文: Java 虚拟机结构 Class文件格式 数据类型 原始类型(基本类型) 数值类型{整数[byte8 short1...

3587
来自专栏java达人

Java虚拟机

1、Java虚拟机是什么 “Java虚拟机“可以指三种不同的东西 抽象规范 一个具体的实现 一个运行中的虚拟机实例 当运行一个Java程序的同时,也就是在运行一...

22510
来自专栏高性能服务器开发

Redis应用总结

首先, 我带大家简单的了解一下Redis Redis常用数据类型(最为常用的数据类型主要有以下五种) ●String ●Hash ●List ●Set ●Sor...

3167
来自专栏java一日一条

Java并发编程之原子变量

原子变量最主要的一个特点就是所有的操作都是原子的,synchronized关键字也可以做到对变量的原子操作。只是synchronized的成本相对较高,需要获...

803

扫码关注云+社区