工厂模式——猫粮公司的演进

猫粮公司的诞生

陀螺是个程序喵,另起炉灶自己开了公司,为了纪念曾经码梦为生的岁月,公司起名为“跑码场”,主要业务是生产猫粮。

一个喵兼顾着研发和运营,终究不是长久之计。于是雇了一个菜喵做学徒,技术怎么样并不在意,陀螺最看重的是菜喵的名字—招财。

很快,第一款产品「鱼香猫粮」上线,陀螺让招财写个线上订单系统,方便顾客网上下单

招财很快写出了代码

工厂模式——猫粮公司的演进

工厂模式——猫粮公司的演进

测试之后上线,一直运行正常。

过了一段时间,陀螺对招财说:“公司目前正在研发一款牛肉猫粮,并且预计在接下来一段时间会上线「薄荷猫粮」、「鸡肉猫粮」等多款新品,你升级一下订单系统应对一下未来可能发生的改变。”

招财接到任务,重构了原来的代码,首先创建了抽象的CatFood,之后所有具体口味的猫粮必须继承该类

工厂模式——猫粮公司的演进

接下来依次是各种口味的猫粮对象

工厂模式——猫粮公司的演进

最后是下单的逻辑

工厂模式——猫粮公司的演进

招财迫不及待地向陀螺展示自己的代码,并介绍到:“老板,我的代码已经能够满足未来的动态变化了,如果再有新口味的产品,只需要创建该产品的对象,然后修改一下order()方法就好了!”

陀螺赞赏地点点头,“看得出来你经过了自己认真的思考,这一点非常好!但是别着急,你有没有听说过开闭原则?”

“开闭原则?听说过,但是仅仅停留在概念上,我记得好像是‘对修改关闭,对扩展开放’,当时为了面试背的还是挺熟的,哈哈哈”

“那你对照开闭原则再看一下你的代码,你觉得你的代码有什么问题?”,陀螺问道。

招财赶紧仔细审视了一下自己的代码,"我知道了,现在的问题是一旦有新产品上线,就需要改动orde()方法,这就是所谓的没有对修改关闭吧,但是有了新的产品你总得有个地方把他new出来啊,这一步是无论如何都无法省略的,我觉得目前的代码是能够满足需求的。"

“你说的没错,设计原则并不是金科玉律,比如未来如果只有零星几个的新口味产品上线的话,你确实没有必要改变现在的代码结构,简单的修改一下order()就可以了,根本不用在意对修改关闭的这种约束。但是你有必要思考一下,如果后期我们研发了数十种乃至上百种产品,这种情况下你该怎么做?”

“除了修改order()方法,我实在没有想出其他的办法...”,招财挠着脑袋回答道。

陀螺不急不慢地解释说:“这种时候,我们可以先识别出代码中哪些是经常变化的部分,然后考虑使用封装,很明显,order()方法中创建对象的部分就是经常需要变化的,我们可以将封装,使其专门用于创造对象。”

工厂模式——猫粮公司的演进

陀螺解释说:“如此一来,我们完成了封装的操作,把生成对象的操作集中在了SimpleCatFoodFactory中。”

招财立即提出了自己的疑问:“我不理解这样做有什么好处,在我看来这只是把一个问题搬到了一个对象里罢了,问题本身依然存在!”

“就创建的过程而言,你说的确实没错。”,陀螺点点头,“但是,我们仍然得到了很多益处,现在我们的SimpleCatFoodFactory不仅仅可以被order()方法使用了,之后的任何相关逻辑都可以调用我们写的这个类,而且如果后续需要改变,我们也仅仅需要改变这个单独的类就可以了”。

招财无奈地回应说,“好吧,你的话确实很有道理,把经常变动的部分提取出来是个不错的代码优化习惯。对了,刚才这种优化技巧有名字吗?”

“这种叫简单工厂,很多开发人员都误以为它是一种设计模式了,但是它其实并不属于GoF23种设计模式,但是由于用的人太多,经常把它和工厂模式一起介绍。至于是不是设计模式,对我们而言并不重要。”

简单工厂并不是一种设计模式,更像是一种编程的优化习惯,用来将对象的创建过程和客户端程序进行解耦

招财并不放弃,继续追问,“那能不能有个办法再优化一下创建对象的过程呢,它现在依然没有满足开闭原则!而且客户端的调用方式非常不优雅,万一参数不小心拼错了,直接就崩了,这种麻烦不应该转嫁到客户端不是吗?”

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzfjgp.html