美文网首页设计模式Android知识Android技术知识
【阿里大神讲设计模式】2.小光热干面提供饮料了---简单工厂

【阿里大神讲设计模式】2.小光热干面提供饮料了---简单工厂

作者: 菜鸟窝 | 来源:发表于2017-04-01 09:22 被阅读123次

    本系列文章由阿里大神 名俊 授权独家发布

    前情提要

    本意是想像美剧的previously那样, 不知道怎么翻译好, 求翻译达人赐教...
    上集讲到, 小光辞了工作, 开起了热干面的店子, 用Builder模式改造了热干面的构建过程, 是日渐稳定有效起来, 生意也是越来越好.

    但是小光是善于观察的同学啊, 他发现热干面真的好干啊(好像一般人也都能发现, 鬼脸~). 心想, 解决用户痛点才产品的存在根本啊, 是时候推出新东西了.

    于是他决定跟推出自己的光氏饮料产品.

    饮料的制作

    经过一番调查和走访, 小光发现几个特点:

    大家对这个饮料要求不高(码农的屌丝特性啊) , 解渴为主.
    因为赶着上班, 一般要求要快, 最好可以直接拿走.
    品种要丰富, 大家口味不一啊.
    于是, 小光选用了最新的XX牌 (有广告商找我吗? 哈哈.) 速溶饮料. 制作饮料的过程很简单, 很快, 小光做出了第一杯饮料---橙汁:

    public class OrangeJuice {
        public void make() {
            // 1. 拿出一次性饮料杯
            System.out.println("拿出一次性饮料杯");
            // 2. 加入速溶橙汁粉
            System.out.println("加入速溶橙汁粉");
            // 3. 加水冲兑
            System.out.println("加水");
            // 4. 加盖, 打包
            System.out.println("加盖, 打包");
        }
    }
    

    小光的思考

    看起来, 程序似乎是可以运转了, 让我们投入生产吧...
    然而, 小光何许人啊, 毕竟是在码农界混了好些年的同志啊. 还没有投入使用, 就发现了"问题":

    饮料有很多种, 过程都类似, 只是放的速溶包不一样. 如果我每个都这么写, 改天真有人找我打广告, 杯子上印个二维码什么的, 我不是每个饮料的制作过程都要改啊

    灵光一现, 小光想起了面向对象思想中提到的抽象, 封装, 于是乎, 小光改写了自己的程序:

    他抽象出来一个"Drink"类:

    public abstract class Drink {
    
        public void make() {
            // 1. 拿出一次性饮料杯
            System.out.println("拿出一次性饮料杯");
            // 2. 加入速溶橙汁粉
            System.out.println("加入" + getInstantPackage());
            // 3. 加水冲兑
            System.out.println("加水");
            // 4. 加盖, 打包
            System.out.println("加盖, 打包");
        }
    
        abstract String getInstantPackage();
    }
    

    可乐, 酸梅汤, 橙汁皆继承了Drink:

    public class Coke extends Drink {
        @Override
        String getInstantPackage() {
            return "速溶可乐粉";
        }
    }
    public class PlumJuice extends Drink {
        @Override
        String getInstantPackage() {
            return "速溶酸梅粉";
        }
    }
    public class OrangeJuice extends Drink {
        @Override
        String getInstantPackage() {
            return "速溶橙汁粉";
        }
    }
    
    

    开卖

    制作完饮料, 准备开卖了, 是这样的:

    public class XiaoGuang {
        public static void main(String[] args) {
            OrangeJuice orangeJuice = new OrangeJuice();
            orangeJuice.make();
        }
    }
    

    第二天, 生意实在太好, 小光请了表妹临时来帮忙泡制饮料. 而且, 小光还发现自己也无需关注用户要什么饮料了, 直接让用户告诉表妹, 表妹直接制作饮料给用户就行~

    表妹负责根据用户要求生产饮料:

    public class Cousins {
    
        public static Drink create(String drinkType) {
            //  Java7开始, switch支持String
            switch (drinkType) {
                case "橙汁":
                    return new OrangeJuice();
                case "酸梅汤":
                    return new PlumJuice();
                case "可乐":
                    return new Coke();
                default:
                    return new OrangeJuice();
            }
        }
    }
    

    小光不再关注饮料具体种类:

    public class XiaoGuang {
        public static void main(String[] args) {
            Drink drink = Cousins.create("可乐");
            drink.make();
        }
    }
    

    加上饮料套餐之后, 生意果然越来越好, 估计也有美女助阵的加成, 哈哈...

    故事之后

    可能有些同学已经看出一点熟悉感了, 我们把这些关系一个UML表示下:


    如此, 应该就比较清晰了, 这个就是我们今天的主题---简单工厂.

    严格来说, 简单工厂并非一种设计模式, 可以说是一种编码习惯.
    那么我们为什么要使用简单工厂, 或者说这么做有什么好处呢?

    从我们这个例子中, 可以看到, 小光(Client类)不需要去关注饮料泡制(Drink make)这个过程了, 有更多的时间去接待客户, 只需从表妹(工厂类)那拿到相应的饮料给客户即可.

    这个其实是蕴含了单一职责的编程思想:

    小光的职责是接待客户
    表妹的职责是泡制饮料
    简单工厂一般来说, 使用一个静态方法来生产产品, 故而有时也称之为静态工厂方法模式.

    扩展阅读

    在这个故事的过程中, 我们提到了面向对象的抽象, 封装特性. 实际上我们所有的OOD原则, 设计模式, 都是基于面向对象的思想的, 离不开抽象, 封装, 继承, 多态几大特性. 随着对这些设计模式的分析, 也可以让我们加深面向对象的编程思想.

    以Glide为例, 其中的DefaultConnectivityMonitorFactory.java就是一个类似的简单工厂实现:

    public class DefaultConnectivityMonitorFactory implements   ConnectivityMonitorFactory {
    
      @NonNull
      public ConnectivityMonitor build(
          @NonNull 
          Context context,
          @NonNull 
          ConnectivityMonitor.ConnectivityListener listener) {
            final int res = context.checkCallingOrSelfPermission("android.permission.ACCESS_NETWORK_STATE");
            final boolean hasPermission = res == PackageManager.PERMISSION_GRANTED;
            if (hasPermission) {
                return new DefaultConnectivityMonitor(context, listener);
            } else {
                return new NullConnectivityMonitor();
            }
      }
    }
    

    与表妹Cousins(工厂)的实现很类似, 只是这个Factory具体创建什么产品不是由传入的参数决定的, 是在内部的逻辑决定的.
    转化为类图关系, 更加清晰:


    一直在说的话: 所谓架构, 设计模式都是一种思想, 没有固定的招式, 所有的这些招式都是让我们入门, 了解面向对象的基础思想, 然后能运用无形. 共勉.

    留个尾子

    大家可能有发现, 简单工厂的弊端也是很多的, 表妹(工厂)的责任太重, 包含(UML依赖关系)了所有的具体产品的实现. 另外, 如果需要修改或增加产品, 我们就得改变工厂类的实现. 这显然违反了开闭原则.

    故而, 简单工厂, 一般来说, 适用于产品类别较少, 且固定的场景.

    更多内容,请关注菜鸟窝(微信公众号ID: cniao5),程序猿的在线学习平台。 转载请注明出处,本文出自菜鸟窝,原文链接http://www.cniao5.com/forum/thread/604a659a102f11e790dc00163e0230fa

    相关文章

      网友评论

        本文标题:【阿里大神讲设计模式】2.小光热干面提供饮料了---简单工厂

        本文链接:https://www.haomeiwen.com/subject/dltiottx.html