无尽加班何时休--状态模式

1.1 加班,又是加班!

        公司的项目很急,所以要求加班。经理把每个人每天的工作都排得满满的,说做完就可以回家,但是没有任何一个人可以在下班前完成的,基本都得加班,这就等于是自愿加班。我走时还有哥们在加班呢。"
        再急也不能这样呀,长时间加班,没有加班费,士气低落,效率大打折扣。

        "可不是咋地!上午刚上班的时候,效率很高,可以写不少代码,到了中午,午饭一吃完,就犯困,可能是最近太累了,但还不敢休息,因为没有人趴着睡觉的,都说项目急,要抓紧。所以我就这么迷迷糊糊的,到了下午三点多才略微精神点,本想着今天任务还算可以,希望能早点完成,争取不要再加班了。哪知快下班时才发现有一个功能是我理解有误,其实比想象的要复杂得多。唉!苦呀,又多花了三个多钟头,九点多才从公司出来。"
        "哈,那你自己也有问题,对工作量的判断有偏差。在公司还可以通过加班来补偿,要是在高考考场上,哪可能加时间,做不完直接就是玩完。"
        "你说这老板对加班是如何想的呢?难道真的认为加班可以解决问题?我感觉这样赶进度,对代码质量没任何好处。"
        "老板的想法当然是和员工不一样了。员工加班,实际上分为几种,第一种,极有可能是员工为了下班能多上会网,聊聊天,打打游戏,或者是为了学习点新东西,所以这其实根本就不能算是加班,只能算下班时坐在办公座位上。第二种,可能这个员工能力相对差,技术或业务能力不过关,或者动作慢,效率低,那当然应该要加班,而且老板也不会打算给这种菜鸟补偿。"

        "我又没说是指你,除非你真的觉得自己能力差、效率低,是菜鸟。"
        "不过也不得不承认,我现在经验不足确实在效率上是会受些影响的,公司里的一些骨灰级程序员,也不觉得水平特别厉害,但是总是能在下班前后就完成当天任务,而且错误很少。"
        "慢慢来吧,编程水平也不是几天就可以升上去的。虽然今天你很累了,但是通过加班这件事,你也可以学到设计模式。"
        "哦,听到设计模式,我就不感觉累了。来,说说看。"
        "你刚才曾讲到,上午状态好,中午想睡觉,下午渐恢复,加班苦煎熬。其实是一种状态的变化,不同的时间,会有不同的状态。你现在用代码来实现一下。"


        "其实就是根据时间的不同,做出判断来实现,是吧?这不是大问题。"

1.2 工作状态--函数版

package code.chapter16.state1;public class Test {static int hour = 0;static boolean workFinished = false; //工作是否完成的标记public static void writeProgram()        {if (hour < 12)System.out.println("当前时间:"+hour+"点 上午工作,精神百倍");else if (hour < 13)System.out.println("当前时间:"+hour+"点 饿了,午饭;犯困,午休。");else if (hour < 17)System.out.println("当前时间:"+hour+"点 下午状态还不错,继续努力");else {if (workFinished)System.out.println("当前时间:"+hour+"点 下班回家了");else {if (hour < 21)System.out.println("当前时间:"+hour+"点 加班哦,疲累之极");else System.out.println("当前时间:"+hour+"点 不行了,睡着了。");}}}public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		hour = 9;writeProgram();hour = 10;writeProgram();hour = 12;writeProgram();hour = 13;writeProgram();hour = 14;writeProgram();hour = 17;//workFinished = true;  //任务完成,下班workFinished = false;   //任务未完成,继续加班writeProgram();hour = 19;writeProgram();hour = 22;writeProgram();System.out.println();System.out.println("**********************************************");}}

要有面向对象的思维,至少应该有个工作类

1.3 工作状态--分类版

package code.chapter16.state2;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		//紧急项目Work emergencyProjects = new Work();emergencyProjects.setHour(9);emergencyProjects.writeProgram();emergencyProjects.setHour(10);emergencyProjects.writeProgram();emergencyProjects.setHour(12);emergencyProjects.writeProgram();emergencyProjects.setHour(13);emergencyProjects.writeProgram();emergencyProjects.setHour(14);emergencyProjects.writeProgram();emergencyProjects.setHour(17);emergencyProjects.setWorkFinished(false);//emergencyProjects.setWorkFinished(true);emergencyProjects.writeProgram();emergencyProjects.setHour(19);emergencyProjects.writeProgram();emergencyProjects.setHour(22);emergencyProjects.writeProgram();System.out.println();System.out.println("**********************************************");}}//工作类
class Work{//时间钟点private int hour;   public int getHour(){return this.hour;}public void setHour(int value){this.hour = value;}//是否完成工作任务private boolean workFinished = false;   public boolean getWorkFinished(){return this.workFinished;}public void setWorkFinished(boolean value){this.workFinished = value;}public void writeProgram()        {if (hour < 12)System.out.println("当前时间:"+hour+"点 上午工作,精神百倍");else if (hour < 13)System.out.println("当前时间:"+hour+"点 饿了,午饭;犯困,午休。");else if (hour < 17)System.out.println("当前时间:"+hour+"点 下午状态还不错,继续努力");else {if (workFinished)System.out.println("当前时间:"+hour+"点 下班回家了");else {if (hour < 21)System.out.println("当前时间:"+hour+"点 加班哦,疲累之极");else System.out.println("当前时间:"+hour+"点 不行了,睡着了。");}}}
}

1.4 方法过长时坏味道

        "仔细看看,MartinFowler曾在《重构》中写过一个很重要的代码坏味道,叫作'Long Method',方法如果过长其实极有可能是有坏味道了。"
        "你的意思是'Work(工作)'类的'writeProgram(写程序)'方法过长了?不过这里面太多的判断,好像是不太好。但我也想不出来有什么办法解决它。"
        "你要知道,你这个方法很长,而且有很多的判断分支,这也就意味着它的责任过大了。无论是任何状态,都需要通过它来改变,这实际上是很糟糕的。"
        "哦,对的,面向对象设计其实就是希望做到代码的责任分解。这个类违背了'单一职责原则'。但如何做呢?"
"说得不错,由于'writeProgram(写程序)'的方法里有这么多判断,使得任何需求的改动或增加,都需要去更改这个方法了,比如,你们老板也感觉加班有些过分,对于公司的办公室管理以及员工的安全都不利,于是发了一个通知,不管任务再多,员工必须在20点之前离开公司。这样的需求很合常理,所以要满足需求你就得更改这个方法,但真正要更改的地方只涉及17~22点的状态,但目前的代码却是对整个方法做改动,维护出错的风险很大。"
        "你解释了这么多,我的理解其实就是这样写方法违背了'开放-封闭原则'。"
        那么我们应该如何做?
        "把这些分支想办法变成一个又一个的类,增加时不会影响其他类。然后状态的变化在各自的类中完成。"理论讲讲很容易,但实际如何做,我想不出来。"
        "当然,这需要丰富的经验积累,但实际上你是用不着再去重复发明'轮子'了,因为GoF已经为我们针对这类问题提供了解决方案,那就是'状态模式'。"

1.5 状态模式

        状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。[DP]

        "状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断很简单,那就没必要用'状态模式'了。"
状态模式(State)结构图

package code.chapter16.state0;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		Context c = new Context(new ConcreteStateA());c.request();c.request();c.request();c.request();System.out.println();System.out.println("**********************************************");}}//抽象状态类
abstract class State {public abstract void handle(Context context);}//具体状态类A
class ConcreteStateA extends State 
{public void handle(Context context) {context.setState(new ConcreteStateB());}
}//具体状态类B
class ConcreteStateB extends State 
{public void handle(Context context) {context.setState(new ConcreteStateA());}
}//上下文
class Context {private State state;public Context(State state){this.state = state;}//可读写的状态属性,用于读取当前状态和设置新状态public State getState(){return this.state;}public void setState(State value){this.state = value;System.out.println("当前状态:" + this.state.getClass().getName());}public void request(){this.state.handle(this); }
}

        State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。
        ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
        Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。

1.6 状态模式的好处与坏处

        "状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来[DP]。"
        "是不是就是将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换[DP]。"
        "说白了,这样做的目的就是为了消除庞大的条件分支语句,大的分支判断会使得它们难以修改和扩展,就像我们最早说的刻版印刷一样,任何改动和变化都是致命的。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖,好比把整个版面改成了一个又一个的活字,此时就容易维护和扩展了。"
        "什么时候应该考虑使用状态模式呢?"
        "当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。另外,如果业务需求某项业务有多个状态,通常都是一些枚举常量,状态的变化都是依靠大量的多分支判断语句来实现,此时应该考虑将每一种业务状态定义为一个State的子类。于是这些对象就可以不依赖于其他对象而独立变化了,某一天客户需要更改需求,增加或减少业务状态或改变状态流程,对你来说都是不困难的事。"
        "哦,明白了,这种需求还是非常常见的。"
        "现在再回过头来看你的代码,那个'Long Method'你现在会改了吗?"

1.7 工作状态--状态模式版

代码结构图

package code.chapter16.state3;public class Test {public static void main(String[] args){System.out.println("**********************************************");		System.out.println("《大话设计模式》代码样例");System.out.println();		//紧急项目Work emergencyProjects = new Work();emergencyProjects.setHour(9);emergencyProjects.writeProgram();emergencyProjects.setHour(10);emergencyProjects.writeProgram();emergencyProjects.setHour(12);emergencyProjects.writeProgram();emergencyProjects.setHour(13);emergencyProjects.writeProgram();emergencyProjects.setHour(14);emergencyProjects.writeProgram();emergencyProjects.setHour(17);emergencyProjects.setWorkFinished(false);//emergencyProjects.setWorkFinished(true);emergencyProjects.writeProgram();emergencyProjects.setHour(19);emergencyProjects.writeProgram();emergencyProjects.setHour(22);emergencyProjects.writeProgram();System.out.println();System.out.println("**********************************************");}
}//抽象状态类
abstract class State {public abstract void writeProgram(Work w);}//上午工作状态
class ForenoonState extends State {public void writeProgram (Work w) {if (w.getHour() < 12)  {System.out.println("当前时间:"+ w.getHour() +"点 上午工作,精神百倍");}else {w.setState(new NoonState());w.writeProgram();}}
}//中午工作状态
class NoonState extends State {public void writeProgram (Work w) {if (w.getHour() < 13)  {System.out.println("当前时间:"+ w.getHour() +"点 饿了,午饭;犯困,午休。");}else {w.setState(new AfternoonState());w.writeProgram();}}
}//下午工作状态
class AfternoonState extends State {public void writeProgram (Work w) {if (w.getHour() < 17) {System.out.println("当前时间:"+ w.getHour() +"点 下午状态还不错,继续努力");}else {w.setState(new EveningState());w.writeProgram();}}  
}//晚间工作状态
class EveningState extends State {public void writeProgram(Work w){if (w.getWorkFinished())  {w.setState(new RestState());w.writeProgram();}else{if (w.getHour() < 21) {System.out.println("当前时间:"+ w.getHour() +"点 加班哦,疲累之极");}else {w.setState(new SleepingState());w.writeProgram();}}}
}//睡眠状态
class SleepingState extends State {public void writeProgram(Work w) {System.out.println("当前时间:"+ w.getHour() +"点 不行了,睡着了。");}
}//下班休息状态
class RestState extends State {public void writeProgram(Work w) {System.out.println("当前时间:"+ w.getHour() +"点 下班回家了");}
}//工作类
class Work {private State current;public Work(){current = new ForenoonState();  }//设置状态public void setState(State value) {this.current = value;}//写代码的状态public void writeProgram() {this.current.writeProgram(this);}//当前的钟点private int hour;public int getHour(){return this.hour;}public void setHour(int value){this.hour = value;}//当前工作是否完成private boolean workFinished = false;public boolean getWorkFinished(){return this.workFinished;}public void setWorkFinished(boolean value){this.workFinished = value;}
}

        抽象状态类,定义一个抽象方法"写程序"。
        上午和中午工作状态类:
        下午和晚间工作状态类:
        睡眠状态和下班休息状态类:
        工作类,此时没有了过长的分支判断语句。
        客户端代码,没有任何改动。但我们的程序却更加灵活易变了。
        "此时的代码,如果要完成我所说的'员工必须在20点之前离开公司',我们只需要怎么样?"
        "增加一个'强制下班状态',并改动一下'晚间工作状态'类的判断就可以了。而这是不影响其他状态的代码的。这样做的确是非常好。"
        "学会了状态模式,我的状态好着呢,让我再体会体会状态模式的美妙。"
        "行了吧你,估计明上午的工作状态,就是睡觉打呼噜了。"
        "唉,这也是公司造成的呀。明天估计还得加班,无尽加班何时休,却道天凉好个秋!"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/301545.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

加州大学欧文分校英语基础语法专项课程02:Questions, Present Progressive and Future Tenses 学习笔记

Questions, Present Progressive and Future Tenses Course Certificate 本文是学习 Questions, Present Progressive and Future Tenses 这门课的学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。 文章目录 Questions, Present Progressive and Future TensesWeek 01: …

Mysql底层原理七:InnoDB 行记录

1.行格式 1.1 Compact行格式 1.1.1 示意图 1.1.2 准备一下 1&#xff09;建表 mysql> CREATE TABLE record_format_demo (-> c1 VARCHAR(10),-> c2 VARCHAR(10) NOT NULL,-> c3 CHAR(10),-> c4 VARCHAR(10)-> ) CHARSETascii ROW_FORMATCOM…

提升自媒体写作效率:7款必备工具推荐! #知识分享#媒体#AI写作

我们做自媒体运营&#xff0c;想要快速的创作内容&#xff0c;提供文章的创作速度是我们的目标&#xff0c;我们别的大佬可以很快地就创作出一篇内容&#xff0c;而自己墨迹半天确出不了一个字呢&#xff1f;其实这关乎到创作技巧&#xff0c;下面小编就跟大家分享如何利用自媒…

如何高效学习Python编程语言

理解Python的应用场景 不同的编程语言有不同的发展历史和应用场景,了解Python主要应用在哪些领域对于学习它会有很大帮助。Python最初是一种通用脚本语言,主要用于系统级任务自动化。随着时间的推移,它逐步成为数据处理、科学计算、Web开发、自动化运维等众多领域的主要编程语…

ES6-2:Iterator、Proxy、Promise、生成器函数...

11-Iterator迭代器 打印出的是里面的内容&#xff0c;如果是for in打印出来的是索引&#xff0c;of不能遍历对象Symbol.iterator是js内置的&#xff0c;可以访问直接对象arr[Symbol.iterator]&#xff0c;()调用对象非线性一般不能迭代 后两个是伪数组&#xff0c;但是是真迭…

Linux 内核:线程的实现

在linux中的线程是轻量级线程&#xff08;Light-Weight-process&#xff0c;LWP&#xff09; 文章目录 线程概念线程实现 线程概念 线程分类 用户级线程内核级线程&#xff0c;没有用户空间&#xff0c;完全工作在内核中&#xff08;下图中没有[]的就是用户级线程&#xff09…

解析以及探讨数据库技术及其应用

一&#xff0c;引言 数据库作为信息时代的基石&#xff0c;是一种用于高效存储、管理和检索大量结构化数据的系统。它的核心价值在于提供了一种可靠且可扩展的方式&#xff0c;将复杂多样的数据按照特定结构和规则组织起来&#xff0c;以便于不同用户和应用程序进行访问和使用。…

蓝桥杯练习系统(算法训练)ALGO-957 P0703反置数

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 一个整数的反置数指的是把该整数的每一位数字的顺序颠倒过来所得到的另一个整数。如果一个整数的末尾是以0结尾&#xff0c;那么在它的…

Linux-等待子进程

参考资料&#xff1a;《Linux环境编程&#xff1a;从应用到内核》 僵尸进程 进程退出时会进行内核清理&#xff0c;基本就是释放进程所有的资源&#xff0c;这些资源包括内存资源、文件资源、信号量资源、共享内存资源&#xff0c;或者引用计数减一&#xff0c;或者彻底释放。…

Qt 实现的万能采集库( 屏幕/相机/扬声器/麦克风采集)

【写在前面】 之前应公司需要&#xff0c;给公司写过一整套直播的库( 推拉流&#xff0c;编解码)&#xff0c;类似于 libobs。 结果后来因为没有相关项目&#xff0c;便停止开发&维护了。 不过里面很多有用的组件&#xff0c;然后也挺好用的&#xff0c;遂开源出来一部分。…

Leetcode - 2009. 使数组连续的最少操作数

文章目录 解析排序 原地去重 滑动窗口AC CODE 题目链接&#xff1a;Leetcode - 2009. 使数组连续的最少操作数 解析 题中所述的连续数组就是一串连续的自然数&#xff0c;想问需要多少次操作能将原数组变为连续的数。 我们排序去重&#xff0c;用逆向思维想能保留的数字数目…

红外疼痛医学分会成立大会暨首届学术交流会即将盛大开幕

2024年4月7日&#xff0c;中国中医药研究促进会官网发布“关于召开红外疼痛医学分会成立大会暨首届学术交流会的第三轮通知”通知&#xff0c;大会开幕在即&#xff0c;这充分显示了官方对此次活动的高度重视。 本次大会将于 2024年4月19日至21日在重庆海兰云天海琴酒店隆重举行…

QT 使用redis ,连接并使用

一.redis安装 链接&#xff1a;https://pan.baidu.com/s/17fXKOj5M4VIypR0y5_xtHw 提取码&#xff1a;1234 1.下载得到文件夹如图 course_redis为安装包。 2.启动Redis服务 把安装包解压到某个路径下即可。 打开cmd窗口&#xff0c;切换到Redis安装路径&#xff0c;输入 r…

从人机界面设计黄金三法则视角看 ChatGPT 的界面设计的“好”与“坏”

热门文章推荐&#xff1a; &#xff08;1&#xff09;《为什么很多人工作 3 年 却只有 1 年经验&#xff1f;》&#xff08;2&#xff09;《一文掌握大模型提示词技巧&#xff1a;从战略到战术巧》&#xff08;3&#xff09;《AI 时代&#xff0c;程序员的出路在何方&#xff1…

Jenkins 安装部署

1、安装下载 官网地址&#xff1a;Jenkins 下载 war 包 1、前置环境 JDK 环境&#xff08;根据 Jenkins 版本不同&#xff0c;需要的 JDK 版本不同&#xff0c;目前需要 JDK11 的版本来支持&#xff09;Maven maven 官网下载压缩包 &#xff0c;并将其传输到服务器&#xf…

模拟多模态大模型gradio使用教程

文章目录 前言一、使用change监听demo1、代码3、网页结果显示4、输入信息结果显示 二、Button功能的demo1、代码2、结果显示3、变换参数结果显示 三、参数gr.Slider滑动demo1、代码2、结果显示3、具有下拉参数代码4、具有下拉结果显示 四、模拟多模态大模型网页demo1、代码2、界…

【机器学习300问】59、计算图是如何帮助人们理解反向传播的?

在学习神经网络的时候&#xff0c;势必会学到误差反向传播&#xff0c;它对于神经网络的意义极其重大&#xff0c;它是训练多层前馈神经网络的核心算法&#xff0c;也是机器学习和深度学习领域中最为重要的算法之一。要正确理解误差反向传播&#xff0c;不妨借助一个工具——计…

测开面经(pytest测试案例,接口断言,多并发断言)

pytest对用户登录接口进行自动化脚本设计 a. 创建一个名为"test_login.py"的测试文件&#xff0c;编写以下测试脚本 import pytest import requests# 测试用例1&#xff1a;验证登录成功的情况 # 第一个测试用例验证登录成功的情况&#xff0c;发送有效的用户名和密…

linux:du和df区别

文章目录 1. 概述2. du 命令2. df 命令3. 区别总结 1. 概述 du 和 df 都是 Linux 系统中用于查看磁盘空间使用情况的命令&#xff0c;但它们的功能和用法有所不同。 2. du 命令 du 是 “disk usage” 的缩写&#xff0c;用于显示文件或目录的磁盘使用情况。du 命令用于查看指…

Redis客户端

2.Redis客户端 安装完成Redis&#xff0c;我们就可以操作Redis&#xff0c;实现数据的CRUD了。这需要用到Redis客户端&#xff0c;包括&#xff1a; 命令行客户端图形化桌面客户端编程客户端 2.1.Redis命令行客户端 Redis安装完成后就自带了命令行客户端&#xff1a;redis-…