招财不慌不忙地回答:“我最近又研究了一下多态和继承,order()方法中的create()方法不做具体操作,将该方法延迟到子类中进行执行。”说罢,招财立刻写了如下代码。
"order()方法只是调用了create()方法而已,是由子公司创建的子类负责具体实现create()方法,湖南分公司和山东分公司对应的代码如下",招财接着解释道。
对应的UML图为
最终顾客的下单方式变成了
“看来真是要对你刮目相看了,你刚刚总结出来的这种思想其实就是大名鼎鼎的工厂方法模式”,陀螺满意地笑了,“工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。”
工厂方法模式:定义一个创建对象的接口,担忧子类决定要实例化的类是哪一个,将类的实例化推迟到了子类。
“啊!”,招财大惊,没想到自己误打误撞研究出了工厂方法模式,“我其实并没有想这么多,只是单纯想解决当下的问题,适应未来的变化而已。”
“我知道,恐怕现在让你总结什么时候该用简单工厂模式,什么时候该用工厂方法模式你也未必说的准确。设计模式也不过是前人不断优化自己的代码总结出来的方法论。不必拘泥于你的优化方式叫什么名字,或者干脆忘掉我刚才说的术语吧,在合适的时机运用合适的方法来解决问题才是最重要的!不要学习了设计模式,就觉得自己手上握着锤子,然后看什么都是钉子。”
“我明白了师傅!但是我听说还有一种关于工厂的设计模式,你要不顺便给我讲讲吧。”
猫粮原材料的工厂“还有一种叫抽象工厂模式,如果你明白了我们系统的一步步优化,这个模式对你来说就太简单了。还是用我们公司的场景给你举例子吧。”
“假如我们想进一步控制分公司生产猫粮的原料,避免每个分公司的原料质量参差不齐。制作猫粮的主要原料都是一样的,都需要肉、燕麦、果蔬、牛磺酸等,但是不同的分公司又有不同的原料生产工艺,抽象工厂就适合于这种场景。”
“那该怎么进行设计呢?”
“这个简单啊,我们可以为每一个分公司创建一个原料工厂,这个原料工厂必须符合我们制定的标准,像这样”,招财写下了伪代码。
"各分公司自己的原料厂必须实现CatFoodIngredientFactory来实现每一个创造方法,以山东分公司为例。"
注:代码中有很多类未给出实现,大家只需理解其中的含义即可
招财继续问道:“现在怎么把各个分公司的原料工厂和猫粮联系起来呢?”
“别急,为了更好的解释抽象工厂,我们需要先改变一下我们的CatFood类。这里只是为了单纯讲解抽象工厂模式而进行的更改,和我们自身的业务逻辑已经没有关系了。”
“接下来的重点就是如何创建具体口味的猫粮了。你觉得怎么让猫粮和原料厂关联起来呢?”
“可以在子类中添加一个原料工厂的对象,猫粮产品对象的时候可以选择某个原料厂进行初始化,这样就实现了猫粮和具体原料之间的解耦,猫粮类只需要知道怎么制作就可以了,比如像这个样子。”
“孺子可教”,陀螺欣慰地说道,“你已经掌握的面向对象的精髓了,那么分公司的代码你也可以写出来了,试试看吧。”
招财很快写出了代码。
“到此为止,我们就用抽象工厂模式完成了业务的改造,顾客下单的逻辑并没有发生变化。为了完整性,我们给出抽象工厂的定义”,陀螺说道。
抽象工厂模式:提供接口,用来创建相关或依赖对象的家族,而不需要明确制定具体类。
招财郁闷地说:“你让我自己写我觉得自己能写出来,你解释这么多,我反而头大了!”