• 【一起学系列】之工厂模式:产品?产品族?


    前言

    在设计模式中关于工厂模式有一点特殊,就标准意义而言我们一般提到的工厂模式一般包括三种:

    • 简单工厂
    • 工厂方法模式
    • 抽象工厂模式

    其实简单工厂不属于设计模式,由于它的使用场景还是比较多的,因此本篇将会一起介绍一下~

    工厂模式意图

    工厂模式属于对象创建型模式,无论是上述三种的哪一种都是为了同一个设计原则即依赖抽象,不要依赖具体

    简单来说就是把复杂对象创建(初始化)的细节或者依赖关系经常可能发生变化的细节交给一个第三方类(工厂类),避免在业务逻辑中书写不必要的内容

    简单工厂模式的简单写法

    简单工厂在实际应用中非常的频繁,假设我们现在需要生产Intel和AMD相关的产品,来看看代码

    静态方法无脑IF | Switch

    public class SimpleFactory {
    
        public static AbstractCPU createCpu (String type) {
            switch (type) {
                case "INTEL":
                    return new IntelCpu();
                default:
                    return new AMDCpu();
            }
    
           /* if ("INTEL".equals(type)) {
                return new IntelCpu();
            } else if ("AMD".equals(type)){
                return new AMDCpu();
            }
            return null;*/
        }
    }
    

    此种方式适合非常单一的场景,快速构建工厂代码,不用过多的思考

    值得注意的是静态方法和普通方法的区别,静态工厂让它不具备继承性,在某些场合可能导致无法扩展的问题,在代码优化层面可以配合枚举,Map等方式继续让代码变得更清爽一些

    工厂方法模式

    意图

    定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Mehod使一个类的实例化延迟到其子类

    工厂方法模式的诞生

    工厂方法用来处理对象的创建,并将这样的行为封装在子类中,这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。

    咱们还是一样,说说人话:

    产品】:最近我们有英特尔和AMD的CPU产品订购方案,您看能不能实现一下相关的代码?

    BOSS】:它们的装配啊,生产啊等等的细节一样吗?

    产品】:嗯嗯,细节流程都是一样的!

    BOSS】:那个谁,小柯啊,工厂方法模式懂吗,去做吧,给你半天时间,好好设计设计。

    开发】:好的!(内心OS:我不会啊!!!)

    HeadFirst 核心代码

    不会的话,只能看书学习啦~

    父级接口

    public abstract class Factory {
    
        /***
         * 产品订购方案
         */
        public AbstractCPU orderCpu () {
            AbstractCPU cpu = generateCpu();
            cpu.show();
            cpu.prepare();
            cpu.box();
    
            // 假设有相同的业务处理逻辑...
            return cpu;
        }
    
        protected abstract AbstractCPU generateCpu();
    }
    

    具体实现

    public class IntelCpuFactory extends Factory {
    
        @Override
        public AbstractCPU generateCpu() {
            return new IntelCpu();
        }
    }
    
    // ****************************************************************
    
    public class AMDCpuFactory extends Factory {
    
        @Override
        public AbstractCPU generateCpu() {
            return new AMDCpu();
        }
    }
    

    工厂方法模式的设计思路

    • Product(Document) 定义工厂方法所创建对象的接口
    • ConcreteProduct(MyDocument)实现Product接口
    • Creator(Factory)声明工厂方法
    • ConcreteCreator(MyFactory)具体的工厂类

    什么场景适用

    在下列情况下可以使用 Factory Method模式:

    • 当一个类不知道它所必须创建的对象的类的时候
    • 当一个类希望由它的子类来指定它所创建的对象的时候
    • 当类将创建对象的职责委托给多个子类中的某一个,并且你希望控制哪一个子类实现的时候

    Code/生活中的实际应用

    例如在工厂生产电池时,对于电池的保管,订货,输送的方式可能完全一致,但是仅型号不一致,因此分别交给A流水线,B流水线进行生产,但是后续的其他流程又是重合的

    UML图

    抽象工厂模式

    意图

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

    抽象工厂模式的诞生

    PS:故事内容承接工厂方法模式的诞生~

    产品】:我… 我好像搞错需求了…

    BOSS】:什么意思???

    产品】:咱们的订单不是仅仅只生成CPU产品,而是要生成英特尔还有AMD的全系列产品…

    BOSS】:你你你你… 之前的功夫都白费了啊!

    产品】:不就是生产东西嘛,反正都是生产,我不管,你要给我实现!

    BOSS】:小柯,委屈你了。

    开发】:好吧,那我能问一个问题吗?未来是不是还有可能要生产华为的,联想的?

    产品】:对!很有可能!如果我们生意做大了!

    HeadFirst 核心代码

    抽象工厂模式着重点在产品族上,开始撸代码吧~

    父级抽象类

    public abstract class AbstractFactory {
    
        /**
         * 创建CPU对象
         * @return CPU对象
         */
        public abstract AbstractCPU createCpu();
    
        /**
         * 创建主板对象
         * @return 主板对象
         */
        public abstract AbstractMotherboard createMainboard();
    }
    

    子类实现

    public class IntelFactory extends  AbstractFactory{
    
        @Override
        public AbstractCPU createCpu() {
            return new IntelCpu();
        }
    
        @Override
        public AbstractMotherboard createMainboard() {
            return new IntelMotherboard();
        }
    }
    
    // *************************************************************
    
    public class AMDFactory extends AbstractFactory{
        @Override
        public AbstractCPU createCpu() {
            return new AMDCpu();
        }
    
        @Override
        public AbstractMotherboard createMainboard() {
            return new AMDMotherboard();
        }
    }
    

    抽象工厂模式的设计思路

    • AbstractProduct 为一类产品对象声明一个接口
    • ConcreteProduct 具体对象
    • AbstractFactory 声明一个创建抽象产品对象的接口
    • ConcreteFactory 具体的产品族工厂

    思路示意图

    工厂方法是不是潜伏在抽象工厂中?

    没错,抽象工厂的方法经常以工厂方法的方式实现,因为抽象工厂的任务通常是定义一个负责创建一组产品的接口,在这个接口内的每个方法都负责创建一个具体的产品,而这种某一个具体的产品的实质就是工厂方法模式的实践

    什么场景适用

    在以下情况可以使用 Abstract Factory 模式:

    • 系统要独立于它的产品的创建、组合和表示时
    • 系统要由多个产品系列中的一个来配置时
    • 当你要强调一系列相关的产品对象的设计以便进行联合使用时
    • 当你提供一个产品类库,而只想显示它们的接口而不是实现时

    Code/生活中的实际应用

    比如上述的情况,观察代码我们可以发现我们其实是把一个产品族进行了封装,如果这个时候要引入华为系列产品,我们完全不用动任何代码,只需要增加一个类即可,非常符合开闭原则

    UML图

    遵循的设计原则

    依赖抽象,而不是依赖具体

    • 无论是简单工厂还是工厂方法,亦或是抽象工厂,都是强调解耦,依赖抽象,不依赖具体

    总结

    相同点:

    • 所有的工厂都是用来封装对象的创建
    • 简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以进行解耦
    • 所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合
    • 依赖倒置原则,指导我们避免依赖具体类型,而要尽量依赖抽象
    • 工厂是很有威力的技巧,帮助我们针对抽象编程,而不是具体类编程

    工厂方法:

    • 工厂方法利用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象
    • 工厂方法允许类将实例化延迟到子类实现

    抽象工厂:

    • 抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中
    • 抽象工厂创建相关的对象家族,而不需要依赖它们的具体类

    相关代码链接

    GitHub地址

    • 兼顾了《HeadFirst》以及《GOF》两本经典书籍中的案例
    • 提供了友好的阅读指导

  • 相关阅读:
    [LeetCOde] Reverse Words in a String III
    [LeetCode] Keyboard Row
    [LeetCode] Number Complement
    [LeetCode] Array Partition I
    [LeetCode] Merge Two Binary Trees
    [LeetCode] Hamming Distance
    FFmpeg在ubuntu下安装及使用
    curl命令备注
    CentOS配置防火墙
    leetcode 21 Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/kkzhilu/p/13264167.html
Copyright © 2020-2023  润新知