你写的代码真的很烂讷

429 阅读7分钟

最近有点 emo,好朋友生病请假几天,他所负责的功能被领导交给了我,负责一些功能的稳定性,最多就修修改改一点。

本着大爱无疆的精神,这个简单的要求是能够应付过来的,但是他和领导都没有提及,这个功能需要迭代更新。

不日,一批业务部门的人找上门,拉着我开启了无聊又冗长的会议,重点要求是由原先的商品库存管理功能,细化到根据商品属性,面积,用量计算成本和盈亏情况。

会议重点很突出,冗长的地方在于核对流程以及公式的设置,作为一名干活的开发者,向来由着领导们各种想法讲出来,只在协商很长还没定的时候才想着讲出自己的方案给他们参考希望终结会议吧。这或许是一位佛系码农能做的妥协了。

梳理了一番需求之后准备看朋友的源码进行迭代开发,最好能够在基础之上扩展速度完成。

沉默在于阅读源码的那一刻,纠结是重写还是迎难而上跟着一块叠山,本身功能复杂的逻辑还是处于面向直接开发,业务逻辑核心都是堆叠在一块。

显然这位伙伴要么就是处于摆烂状态,就是缺乏代码的抽象结构化。

作为一名码农,就算是摆烂状态,不想设计复杂的模式应对变化,也不应该功能一把 solo 送上线,哪里痛治哪里。如果他跑了,痛苦的就是交接的朋友了。

想起自己刚出来工作那会,从没想过什么代码能够抽象化,能够用上设计模式。那本老师推荐的《大话设计模式》都是在我的书架上落灰。

直到我遇见一位阿里的码农,那时候跟阿里有业务往来,会有对接。我那时候处于菜鸟形态,每天都得跟他巴拉巴拉功能和需求,他有些冷酷,有时候已读不回。

不知道出于何种心态,也许是关照我初出茅庐,他发了一份 demo 给我,我一天都在看他的源码,已经不是看懂代码的问题了,而是思考什么样的人能够写出这么漂亮的代码,井井有条,要结构有结构,还抽象。

那天晚上,我加班到 22 点,那时走在深夜的街道显得孤独而又安静,而自己的内心又久久不能平复。甚至发了一条朋友圈来感叹。

图片

从那之后,我重新走起了代码整洁而又抽象的道路,要求自己写代码像写文章一样华丽而又严谨。

直到现在,如回到原点,重新梳理设计模式篇章,记录下来给自己回味,也给自己的朋友学习学习。

设计模式也许只是一个策略名词。我们在编码过程中或多或少都有用到,自己本身具备抽象化思维,用到了也并没有指名道姓是何种设计模式,或许是最高境界无招胜有招。

当然,在我们接触计算机后并从事相关工作,已经具备一门语言的能力,那我们就很有必要去学习一下《设计模式》这些前人拥有丰富编程经验进而总结出来的技巧。

我们要先学习它是什么,为什么用,怎么用。我们可以举一个生活中出现的例子,来分析为什么要使用设计模式。

假如我们带好兄弟去吃西餐厅时,想点一份牛排,你可能会想点一份 8 分熟的牛排,你的好友可能会点 7 分熟的牛排,其他人可能会想一份半熟或者纯素牛排。

图片

所以每个人的口味不同,点餐方式也会不同。但是准备牛排的厨师,可以使用同一块肉,根据根据订单的口味需求,会为每位顾客准备一顿不同的牛排。

图片

为了将其特征能够在计算机上体现,我们一般会创建一个 Chef 类(即厨师),并有一个准备的方法 prepare(),并且这个 prepare() 方法可以使用 WellDoneInstruction 对象,即全熟牛排。

在这这个整备 prepare() 方法中,我们可以做一块全熟的牛排,但是九分熟,五分熟的牛排呢?

如果是半分熟:prepare(MediumDone...),素食牛排:prepare(MediumDoneInstruction)。

图片

图上可以看出,为了能够制作出不同口味牛排,我们为 prepare() 方法进行重载来满足,全熟、半熟、素食牛排。

如果说餐厅扩展了其他的口味,我们依然只是在这基础之上进行重载,这里就会有很多的重载方法,意味着随时都有可能增加更多的方法。

在这基础之后我们可以将这些方法替换为一个接受牛排烹饪指令的方法。并让那些具体口味烹饪的牛排都继承至 Chef  类,那么我们就不需要再改动 Chef 类了。

图片

这里我们的 Chef 类关闭了修改功能,开放了 扩展功能。

这里我们举了日常生活中的例子,将生活实例映射到计算机层面去体现。艺术往往来源于生活。

图片

接下来我们将会一起重温  23 种经典设计模式,每一种设计模式关联性不强,很有必要每一个设计模式都学习一遍。

其中 23 种设计模式又分为:创建型模式、结构型模式、行为型模式

创建型模式

处理对象的创建,它不是明确,具体地实例化所有对象,它将为我们实际创建对象的方式提供了更大的灵活性。

比如说,我们的类有 10 个属性,在实际使用过程中我们并不是所有属性都用到,有时候只是 1-2 个,有时候是 4-6个不等,传统的方式会创建一个方法,将10个属性都放入作为传参,如果不需要的就传 null。

图片

但是如果使用设计模式,我们可以遵循构建器模式提供模板。

结构型模式

处理类的实际设计方式,以及如何使用继承、组合和聚合等内容,以此来提供额外的功能。

例如我们在存储书籍的对象,而这些书籍实在是太多了,当当网存储的书籍,成千上万的书籍。

假如某种情况,我们使用一个对象来表示每本书,这种情况下我们会有一堆共享属性的书籍对象,比如说作者、年份、实体书存储位置、出版社等等。

存在不同最多的是书的名字或者书的编码,我们就没必要创建如此多的对象,浪费大量的内存和空间,如果我们使用 23 种设计模式中的享元模式,来指定统一模板。

通过共享尽可能多的数据来最大限度地减少内存使用。这就是设计模式需要做的事情。

行为型模式

特别关注程序运行时对象之间的通信和职责分配。

例如应用程序中的一个对象的状态被许多其他对象更改,但我们需要撤销最后一次更改,并且我们可以自由的使用其中任何一个。

如此,我们可以使用 23 种设计模式中的备忘录模式进行完成。因为它是由许多案例验证并且测试过的。

图片

我们有时候并不知道什么情况下使用什么样的设计模式,以及开发过程中更是不知不觉其实已经有设计模式的雏形。

但随着时间的推移,以及经验的不断积累,我们会将设计模式运用更加成熟。

为此我也会将 23 种设计模式进行分享,以更加生动有趣的方式进行。

我们不希望通过拗口的抽象理论描述使得晦涩难懂,而是通过融会贯通后组织的语言进行分享,使得初学者都能够看得明白。

也有《大话设计模式》、《JavaScript 设计模式与开发实践》等设计模式类的文档书籍,汇集各类需求的内容,如有需要公众后台回复:设计模式