2025年3月30日 星期日 甲辰(龙)年 月廿九 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > 设计模式

光氏饮品升级了---工厂方法模式

时间:03-13来源:作者:点击数:1

前情提要

上集讲到, 小光的热干面店, 开始搭配提供饮料了. 再加上美女表妹的助阵, 生意是红红火火啊.

然而, 事情也不是尽善尽美的, 慢慢小光就听到了一些的客户的声音: 酸梅汤太酸了, 能调好点吗? 天冷了能来点热饮吗?

客户可是上帝啊, 小光立马就着手改进.

所有示例源码已经上传到Github, 戳这里

表妹的抱怨

带着客户的声音, 小光找表妹聊了下, 想让表妹修改下当前的酸梅汤泡制比例, 另外再增加一些热饮的泡制.

没想到, 表妹一听到着就很反对: "我现在已经记得太多了, 你这么不定时的修改, 增加, 我更容易记混, 到时候更出问题了". (职责太重)

小光一想, 是啊, 我把自己从做热干面添加各种配料的烦恼中释放出来了(通过Builder模式). 不能让表妹也陷入这样的烦恼啊.

解决之路

可是怎么才能更好的解决这个问题呢?

要是我有很多个表妹就好了, 每个表妹负责一种饮料的泡制, 小光想着. 嗯~, 很多个表妹?! 小光微微一笑, 计上心头.

小光买来很多个迷你饮水机, 一个装一种饮料, 并且贴上相应的标签, 如此这般:

每个迷你饮水机作为一个饮料机, 用来生产不同的饮料. 表妹只有根据用户的需求选择不同的饮料机打出饮料即可.

这样, 表妹也无需关注饮料的生产过程了, 不用记那么多的饮料配置方式了. 如果想要新增饮品, 再弄一台饮料机就行了.

来看看对应关系

这是没有标签的饮水机(饮料机):

  • public interface IBeverageMachine {
  • Drink makeDrink();
  • }

这是贴了不同饮料类型的饮料机:

  • public class OrangeJuiceMachine implements IBeverageMachine {
  • @Override
  • public Drink makeDrink() {
  • return new OrangeJuice().make();
  • }
  • }
  • public class CokeMachine implements IBeverageMachine {
  • @Override
  • public Drink makeDrink() {
  • return new Coke().make();
  • }
  • }
  • public class PlumJuiceMachine implements IBeverageMachine {
  • @Override
  • public Drink makeDrink() {
  • return new PlumJuice().make();
  • }
  • }

这是那些饮料(还是有一个抽象继承关系):

  • public abstract class Drink {
  • private String name;
  • private String instantPackage;
  • public Drink make() {
  • this.name = getName();
  • this.instantPackage = getInstantPackage();
  • return this;
  • }
  • abstract String getInstantPackage();
  • abstract String getName();
  • @Override
  • public String toString() {
  • return "This is a cup of:" + this.name;
  • }
  • }
  • public class Coke extends Drink {
  • @Override
  • String getInstantPackage() {
  • return "速溶可乐粉";
  • }
  • @Override
  • String getName() {
  • return "可乐";
  • }
  • }
  • public class OrangeJuice extends Drink {
  • @Override
  • String getInstantPackage() {
  • return "速溶橙汁粉";
  • }
  • @Override
  • String getName() {
  • return "橙汁";
  • }
  • }
  • public class PlumJuice extends Drink {
  • @Override
  • String getInstantPackage() {
  • return "速溶酸梅粉";
  • }
  • @Override
  • String getName() {
  • return "酸梅汤";
  • }
  • }

相比上一篇简单工厂中的饮料, 我们将打包这个操作从饮料这个对象中移除了, 目前的饮料对象中只是一些简单的属性.

为什么要这么做呢? 大家可以用自己面向对象编程思想的脑洞自由发挥下, 下期说说我的想法.

现在表妹的工作就变得简单了:

  • public class Cousins {
  • private IBeverageMachine mBeverageMachine;
  • private void setBeverageMachine(IBeverageMachine machine) {
  • this.mBeverageMachine = machine;
  • }
  • private Drink takeDrink() {
  • if (mBeverageMachine == null) throw new NullPointerException("Should set Beverage Machine firstly.");
  • return mBeverageMachine.makeDrink();
  • }
  • public static void main(String[] args) {
  • Cousins cousins = new Cousins();
  • // for A
  • cousins.setBeverageMachine(new OrangeJuiceMachine());
  • Drink drink = cousins.takeDrink();
  • System.out.println(drink);
  • // for B
  • cousins.setBeverageMachine(new CokeMachine());
  • System.out.println(cousins.takeDrink());
  • }
  • }

当A要橙汁时, 表妹去OrangeJuiceMachine装一杯, 当B需要可乐时, 表妹再去CokeMachine拿:

  • This is a cup of:橙汁
  • This is a cup of:可乐

表妹的工作变得更简单了, 工作效率也更高了, 也更能微笑面对顾客了, 哈哈...

想要奶茶的C顾客

这天, 来了一位顾客D, 问: "老板, 有没有热奶茶啊?". 考验小光的程序的时候到了. 很快, 小光copy出了一个奶茶机(扩展开放), 同时也无需修改原来的那些个饮料机程序(修改关闭), 不会因此而耽误生意.

新增奶茶饮料:

  • public class MilkTea extends Drink {
  • @Override
  • String getInstantPackage() {
  • return "速溶奶茶粉";
  • }
  • @Override
  • String getName() {
  • return "奶茶";
  • }
  • }

奶茶机:

  • public class MilkTeaMachine implements IBeverageMachine {
  • @Override
  • public Drink makeDrink() {
  • return new MilkTea().make();
  • }
  • }

现在的台面:

表妹的工作也很简单, 去奶茶机那儿接奶茶就是了:

  • // for D
  • cousins.setBeverageMachine(new MilkTeaMachine());
  • System.out.println(cousins.takeDrink());

D拿到的:

  • This is a cup of:奶茶

故事之后

照例, 我们先来画出现在的类对应关系:

实际上这个就是工厂方法模式.

几个点:

1, 为何叫工厂方法, 是因为每个工厂有一个方法来创建产品.

2, 每个产品对应一个工厂实例来生产这个产品实例.

3, 因为产品和其对应的工厂都与其他产品分离, 我们可以很轻易的去增加新的产品和其对应的工厂, 而不改变原来的结构. (开闭原则, 实际上还蕴含了职责单一)

扩展阅读

工厂方法模式如同Buidler模式, 是一些开源库中非常常见的用来创建实例的设计模式.

例如OkHttp中ModelLoader相关的实现:

看对应关系就跟清晰了, 就不一一类比了.

小光看着这一排饮料机, 成就感悠然而生, 仿佛又回到了那个彻夜编码的岁月.

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐