自学内容网 自学内容网

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

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

加班,又是加班!

时间:4月19日23点  地点:小菜、大鸟住所的客厅  人物:小菜、大鸟

"小菜,你们的加班没完没了了?"大鸟为晚上十点才到家的小菜打开了房门。

“唉,没办法,公司的项目很急,所以要求要加班。”

“有这么急吗?这星期四天来你都在加班,有加班费吗?难道周末也要继续?”

"哪来什么加班费,周末估计是逃不了了。"小菜显然很疲惫,“经理把每个人每天的工作都排得满满的,说做完就可以回家,但是没有任何一个人可以在下班前完成的,基本都得加班,这就等于是自愿加班。我走时还有哥们在加班呢。”

“再急也不能这样呀,长时间加班,没有加班费,士气低落,效率大打折扣。”

“可不是咋地!上午刚上班的时候,效率很高,可以写不少代码,到了中午,午饭一吃完,就犯困,可能是最近太累了,但还不敢休息,因为没有人趴着睡觉的,都说项目急,要抓紧。所以我就这么迷迷糊糊的,到了下午三点多才略微精神点,本想着今天任务还算可以,希望能早点完成,争取不要再加班了。哪知快下班时才发现有一个功能是我理解有误,其实比想象的要复杂得多。唉!苦呀,又多花了三个多钟头,九点多才从公司出来。”

“哈,那你自己也有问题,对工作量的判断有偏差。在公司还可以通过加班来补偿,要是在高考考场上,哪可能加时间,做不完直接就是玩完。”

“你说这老板对加班是如何想的呢?难道真的认为加班可以解决问题?我感觉这样赶进度,对代码质量没任何好处。”

“老板的想法当然是和员工不一样了。员工加班,实际上分为几种,第一种,极有可能是员工为了下班能多上会网,聊聊天,打打游戏,或者是为了学习点新东西,所以这其实根本就不能算是加班,只能算下班时坐在办公座位上。第二种,可能这个员工能力相对差,技术或业务能力不过关,或者动作慢,效率低,那当然应该要加班,而且老板也不会打算给这种菜鸟补偿。”

"大鸟,讽刺我呀。"小菜有些不满。

“我又没说是指你,除非你真的觉得自己能力差、效率低,是菜鸟。”

“不过也不得不承认,我现在经验不足确实在效率上是会受些影响的,公司里的一些骨灰级程序员,也不觉得水平特别厉害,但是总是能在下班前后就完成当天任务,而且错误很少。”

“慢慢来吧,编程水平也不是几天就可以升上去的。虽然今天你很累了,但是通过加班这件事,你也可以学到设计模式。”

“哦,听到设计模式,我就不感觉累了。来,说说看。”

“你刚才曾讲到,上午状态好,中午想睡觉,下午渐恢复,加班苦煎熬。其实是一种状态的变化,不同的时间,会有不同的状态。你现在用代码来实现一下。”

在这里插入图片描述

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

工作状态——函数版

半小时后,小菜的第一版程序。

在这里插入图片描述

“小菜,都学了这么长时间的面向对象开发,你怎么还在写面向过程的代码呀?”“啊,我习惯性思维了,你意思是说要分一个类出来。”

“这是起码的面向对象思维呀,至少应该有个’工作’类,你的’写程序’方法是类方法,而’钟点’'工作任务完成’其实就是类的什么?”

“应该是对外属性,是吧?”

"问什么问,还不快去重写。"大鸟不答反而催促道。

工作状态——分类版

十分钟后小菜写出了第二版程序。

工作类:

在这里插入图片描述

客户端代码:

在这里插入图片描述

方法过长是坏味道

“若是’任务完成’,则17点、19点、22点都是’下班回家了’的状态了。”

"好,现在我来问你,这样的代码有什么问题?"大鸟问道。

“我觉得没什么问题呀,不然我早改了。”

“仔细看看,MartinFowler曾在《重构》中写过一个很重要的代码坏味道,叫作’Long Method’,方法如果过长其实极有可能是有坏味道了。”

“你的意思是’Work(工作)'类的’writeProgram(写程序)'方法过长了?不过这里面太多的判断,好像是不太好。但我也想不出来有什么办法解决它。”

“你要知道,你这个方法很长,而且有很多的判断分支,这也就意味着它的责任过大了。无论是任何状态,都需要通过它来改变,这实际上是很糟糕的。”

“哦,对的,面向对象设计其实就是希望做到代码的责任分解。这个类违背了’单一职责原则’。但如何做呢?”

“说得不错,由于’writeProgram(写程序)'的方法里有这么多判断,使得任何需求的改动或增加,都需要去更改这个方法了,比如,你们老板也感觉加班有些过分,对于公司的办公室管理以及员工的安全都不利,于是发了一个通知,不管任务再多,员工必须在20点之前离开公司。这样的需求很合常理,所以要满足需求你就得更改这个方法,但真正要更改的地方只涉及17~22点的状态,但目前的代码却是对整个方法做改动,维护出错的风险很大。”

“你解释了这么多,我的理解其实就是这样写方法违背了’开放-封闭原则’。”

“哈,小菜总结得好,对这几个原则理解得很透嘛。那么我们应该如何做?”

"把这些分支想办法变成一个又一个的类,增加时不会影响其他类。然后状态的变化在各自的类中完成。"小菜说道,“理论讲讲很容易,但实际如何做,我想不出来。”

“当然,这需要丰富的经验积累,但实际上你是用不着再去重复发明’轮子’了,因为GoF已经为我们针对这类问题提供了解决方案,那就是’状态模式’。”

状态模式

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

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

在这里插入图片描述

State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。

在这里插入图片描述

ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。

在这里插入图片描述

状态模式的好处与用处

“状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来[DP]。”

“是不是就是将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换[DP]。”

“说白了,这样做的目的就是为了消除庞大的条件分支语句,大的分支判断会使得它们难以修改和扩展,就像我们最早说的刻版印刷一样,任何改动和变化都是致命的。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖,好比把整个版面改成了一个又一个的活字,此时就容易维护和扩展了。”

“什么时候应该考虑使用状态模式呢?”

"当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。另外,如果业务需求某项业务有多个状态,通常都是一些枚举常量,状态的变化都是依靠大量的多分支判断语句来实现,此时应该考虑将每一种业务状态定义为一个State的子类。

于是这些对象就可以不依赖于其他对象而独立变化了,某一天客户需要更改需求,增加或减少业务状态或改变状态流程,对你来说都是不困难的事。"

“哦,明白了,这种需求还是非常常见的。”

“现在再回过头来看你的代码,那个’Long Method’你现在会改了吗?”

“哦,学了状态模式,有点感觉了,我试试看。”

工作状态——状态模式版

半小时后,小菜写出了第三版程序。

代码结构图:

在这里插入图片描述

抽象状态类,定义一个抽象方法"写程序"。

在这里插入图片描述

下午和晚间工作状态类:

在这里插入图片描述

工作类,此时没有了过长的分支判断语句。

在这里插入图片描述

“此时的代码,如果要完成我所说的’员工必须在20点之前离开公司’,我们只需要怎么样?”

“增加一个’强制下班状态’,并改动一下’晚间工作状态’类的判断就可以了。而这是不影响其他状态的代码的。这样做的确是非常好。”

"哟,都半夜12点多了,快点睡觉吧。"大鸟提醒道。

“学会了状态模式,我的状态好着呢,让我再体会体会状态模式的美妙。”

“行了吧你,估计明上午的工作状态,就是睡觉打呼噜了。”

“唉,这也是公司造成的呀。明天估计还得加班,无尽加班何时休,却道天凉好个秋!”

如果对你有帮助,就一键三连呗(关注+点赞+收藏),我会持续更新更多干货~~


原文地址:https://blog.csdn.net/m0_63526467/article/details/142652987

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!