• 抽象工厂模式


    思考抽象工厂模式

    抽象工厂专注于产品簇的实现,主要是那些有关联关系的,如果只有一个产品的话就退化成了工厂方法模式

    总结:

    • 简单工厂就是创建了一个工厂,直接在工厂中if-else决定实现哪个类
    • 工厂方法就是一个抽象工厂对应多个具体的工厂实现,里面决定实现哪些产品,也就是延伸到子类中去实现,但只是一个产品,多个产品就不行了,得用抽象工厂
    • 抽象工厂就是多个有关联关系的产品,形成一个产品簇,抽象工厂的实现类进行组合

    1.抽象工厂模式的本质

    抽象工厂模式的本质:选择产品簇的实现。

    产品簇(Product family)指具有相同或相似的功能结构或性能,共享主要的产品特征、组件或子结构,并通过变型配置来满足特定市场的一组产品的聚类。

    工厂方法是选择单个产品的实现,虽然一个类里面可以有多个工厂方法,但是这些方法之间一般是没有联系的,即使看起来像有联系。

    但是抽象工厂着重的就是为一个产品簇选择实现,定义在抽象工厂里面的方法通常是有联系的,它们都是产品的某一部分或者是相互依赖的。如果抽象工厂里面只定义一个方法,直接创建产品,那么就退化成为工厂方法了。

    2.何时选用抽象工厂模式

    建议在以下情况中选用抽象工厂模式。

    • 如果希望一个系统独立于它的产品的创建、组合和表示的时候。换句话说,希望一个系统只是知道产品的接口,而不关心实现的时候。
    • 如果一个系统要由多个产品系列中的一个来配置的时候。换句话说,就是可以动态地切换产品簇的时候。
    • 如果要强调一系列相关产品的接口,以便联合使用它们的时候。

    3.优缺点

    抽象工厂模式的优点

    • 分离接口和实现
      客户端使用抽象工厂来创建需要的对象,而客户端根本就不知道具体的实现是谁,客户端只是面向产品的接口编程而已。也就是说,客户端从具体的产品实现中解耦。

    • 使得切换产品簇变得容易
      因为一个具体的工厂实现代表的是一个产品簇,比如上面例子的Schemel代表装机方案一:Intel的 CPU+技嘉的主板,如果要切换成为Scheme2,那就变成了装机方案二:AMD的CPU +微星的主板。

    客户端选用不同的工厂实现,就相当于是在切换不同的产品簇。

    抽象工厂模式的缺点

    • 不太容易扩展新的产品
      前面也提到这个问题了,如果需要给整个产品簇添加一个新的产品,那么就需要修改抽象工厂,这样就会导致修改所有的工厂实现类。在前面提供了一个可以扩展工厂的方式来解决这个问题,但是又不够安全。如何选择,则要根据实际应用来权衡。

    • 容易造成类层次复杂
      在使用抽象工厂模式的时候,如果需要选择的层次过多,那么会造成整个类层次变得复杂。
      举个例子来说,就比如前面讲到的DAO的示例,现在这个DAO只有一个选择的层次,也就是选择是使用关系型数据库来实现,还是用Xml来实现。现在考虑这样一种情况,如果关系型数据库实现里面又分成几种,比如,基于Oracle的实现、基于SqlServer的实现、基于MySql 的实现等。
      那么客户端怎么选择呢?不会把所有可能的实现情况全部都做到一个层次上吧,这个时候客户端就需要一层一层地选择,也就是整个抽象工厂的实现也需要分出层次来,每一层负责一种选择,也就是一层屏蔽一种变化,这样很容易造成复杂的类层次结构。

    4.抽象工厂模式的结构

    在这里插入图片描述

    • Abstract Factory:抽象工厂,定义创建一系列产品对象的操作接口。
    • Concrete Factory:具体的工厂,实现抽象工厂定义的方法,具体实现一系列产品对象的创建。
    • Abstract Product:定义一类产品对象的接口。
    • Concrete Product:具体的产品实现对象,通常在具体工厂里面,会选择具体的产品实现对象,来创建 - 符合抽象工厂定义的方法返回的产品类型的对象。
    • Client:客户端,主要使用抽象工厂来获取一系列所需要的产品对象,然后面向这些产品对象的接口编程,以实现需要的功能。

    5.实现

    在这里插入图片描述

    cpu产品

    /**
     * @description:cpu接口
     */
    public interface Cpu {
    
        /**
         * 初始化cpu
         */
        void initCpu();
    }
    
    /**
     * @description:英特尔cpu
     */
    public class IntelCpu implements Cpu{
        //针脚
        private int pins=0;
    
        public IntelCpu(int pins){
            this.pins=pins;
        }
    
        @Override
        public void initCpu() {
            System.out.println("Cpu-->英特尔 针脚数"+pins);
        }
    }
    
    /**
     * @description:AMDcpu
     */
    public class AmdCpu implements Cpu{
    
        private int pins=0;
    
        public AmdCpu(int pins){
            this.pins=pins;
        }
    
        @Override
        public void initCpu() {
            System.out.println("Cpu-->AMD 针脚数"+pins);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    主板接口

    /**
     * @description:主板接口
     */
    public interface Mainboard {
    
        /**
         * 初始化主板
         */
        void initMainBoard();
    }
    
    /**
     * @description:华硕主板
     */
    public class AsusMainboard implements Mainboard{
        //针脚
        private int pins=0;
    
        public AsusMainboard(int pins){
            this.pins=pins;
        }
    
        @Override
        public void initMainBoard() {
            System.out.println("Mainboard-->华硕 针脚数"+pins);
        }
    }
    
    /**
     * @description:微星主板
     */
    public class MsiMainboard implements Mainboard{
    
        private int pins=0;
    
        public MsiMainboard(int pins){
            this.pins=pins;
        }
    
        @Override
        public void initMainBoard() {
            System.out.println("Mainboard-->微星 针脚数"+pins);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    抽象工厂

    /**
     * @description:抽象工厂
     */
    public interface AbstractFactory {
    
        /**
         * 创建cpu
         * @return
         */
        Cpu createCpu();
    
        /**
         * 创建主板
         * @return
         */
        Mainboard createMainboard();
    }
    
    /**
     * @description:自组电脑1 (英特尔cpu+华硕主板) 假设都是1156针脚
     */
    public class CustomComputer1 implements AbstractFactory{
        @Override
        public Cpu createCpu() {
            return new IntelCpu(1156);
        }
    
        @Override
        public Mainboard createMainboard() {
            return new AsusMainboard(1156);
        }
    }
    
    /**
     * @description:自组电脑2 (AMDcpu + 微星主板) 假设都是963针脚
     */
    public class CustomComputer2 implements AbstractFactory{
        @Override
        public Cpu createCpu() {
            return new AmdCpu(963);
        }
    
        @Override
        public Mainboard createMainboard() {
            return new MsiMainboard(963);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    组装类

    /**
     * @description:工程师组装电脑
     */
    public class Engineer {
    
        /**
         * cpu
         */
        private Cpu cpu=null;
    
        /**
         * 主板
         */
        private Mainboard mainboard=null;
    
        /**
         * 组装电脑
         * @param factory
         */
        public void makeComputer(AbstractFactory factory){
            cpu=factory.createCpu();
            mainboard=factory.createMainboard();
    
            cpu.initCpu();
            mainboard.initMainBoard();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    测试

    public class Client {
    
        public static void main(String[] args) {
            Engineer engineer = new Engineer();
            //顾客想组装的电脑配置
            engineer.makeComputer(new CustomComputer1());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    类图
    在这里插入图片描述

  • 相关阅读:
    JedisPool
    网页js实现的各种3D树形结构模型
    【企业动态】复工啦,回顾2023,展望2024!东胜物联与您同启新程
    React报错之Cannot find namespace context
    M4Singer Ubuntu 4060ti16G 笔记
    MYSQL的事务、视图、索引、数据备份和恢复
    文件描述符与锁定状态在系统层面的表示
    已解决SyntaxError: invalid character ‘(‘ (U+FF08)
    正则表达式符号
    java-php-net-python-新生量化训练系统计算机毕业设计程序
  • 原文地址:https://blog.csdn.net/qq_42665745/article/details/127986936