掌握抽象工厂模式,打造高效可扩展的软件帝国

简介: 抽象设计模式是软件开发中的重要概念,它为构建灵活、可维护的软件系统提供了强大的支持。本文深入探讨了抽象设计模式的核心思想和应用技巧,旨在帮助读者更好地理解和运用这一设计模式。文章首先介绍了抽象设计模式的基本概念和原理,阐述了其在降低耦合度、提高可扩展性方面的优势。接着,通过具体实例展示了抽象设计模式在实际项目中的应用场景和效果,让读者能够直观地感受到其强大的实用价值。最后,文章总结了抽象设计模式的关键点和注意事项,为读者在实践中运用该模式提供了有益的指导。通过本文的学习,读者将能够更深入地理解抽象设计模式,提升软件开发的效率和质量。

💪🏻 制定明确可量化的目标,坚持默默的做事。


抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,用于在不指定具体类的情况下创建一系列相关或相互依赖的对象。它提供了一个接口,用于创建一系列“家族”相关依赖对象,而无需指定它们的具体类。

       

主要参与者:

  1. 抽象工厂(Abstract Factory):提供一个接口,用于创建一些相关或相互依赖的对象家族,而不需要指定它们具体的类。
  2. 具体工厂(Concrete Factory):实现抽象工厂的操作以生产具体的产品对象。
  3. 抽象产品(Abstract Product):为一系列产品对象声明一个接口。
  4. 具体产品(Concrete Product):抽象产品的子类,定义用于生产的具体产品对象。
  5. 客户(Client):仅使用由抽象工厂和抽象产品类声明的接口。

实现步骤:

  1. 定义抽象产品,确定产品家族中的不同产品。
  2. 创建抽象工厂类,定义创建抽象产品的接口。
  3. 实现具体工厂类,每个工厂类负责创建不同的产品变体。
  4. 客户端代码通过抽象工厂和抽象产品类接口与工厂和产品交互。

优势:

  • 隔离具体类的生成:客户端不需要知道它所使用的对象的具体类,只需要关心所使用对象的接口。
  • 易于交换产品系列:因为具体的工厂类都派生自同一个抽象类,可以很容易地更换使用的工厂类来切换整个产品系列。
  • 增强一致性:产品在一系列中一致地创建,这保证了客户端始终只使用同一产品系列中的对象。

缺点:

  • 难以支持新种类的产品:如果需要添加额外的产品到系列中,抽象工厂和所有具体工厂类都需要改变,这违反了开闭原则。

一、案例

       场景:造一辆汽车(买零件来组装),汽车有很多的零组成,成百上千个零件相互依赖配合工作,比如发动机和变速箱。

       选择零件时,每个零件的品牌、规格 等如何才能选择到合适的搭配才能配合正常工作,也就是说汽车是一个整体,每个零件之间有关联的。

1.1 示例代码

       汽车零件有成百上升个,这里只举例发动机和变速箱。市面上有各种品牌的发动机和变速箱,同一品牌还有各种型等,这里举两个。

 1.1.1 简单工厂实现

        发动机接口:

public interface EngineApi {
    void run();
}

       变速箱接口:

public interface GearboxApi {
    void run();
}

       林肯发动机和林肯变速箱:

public class LinkenEngineApiImpl implements EngineApi {
    @Override
    public void run() {
        System.out.println("林肯发动机工作了");
    }
}
public class LinkenGearboxApiImpl implements GearboxApi {
    @Override
    public void run() {
        System.out.println("林肯变速箱工作了");
    }
}

       丰田发动机和丰田变速箱:

public class ToyotaEngineApiImpl implements EngineApi {
    @Override
    public void run() {
        System.out.println("丰田发动机工作了");
    }
}
public class ToyotaGearboxApiImpl implements GearboxApi {
    @Override
    public void run() {
        System.out.println("丰田变速箱工作了");
    }
}

       发动机工厂:

public class EngineFactory {
    public static EngineApi getEngineApi(int i) {
            if (i == 1) {
                return new LinkenEngineApiImpl();
            }
            return new ToyotaEngineApiImpl();
        }
}

       变速箱工厂

public class GearboxFactory {
    public static GearboxApi getGearbox(int i) {
        if (1 == i) {
            return new LinkenGearboxApiImpl();
        }
        return new ToyotaGearboxApiImpl();
    }
}

       汽车组装类:

public class CarEngineer {
    public void makeCar(int engineType, int gearboxType) {
        EngineApi engineApi = EngineFactory.getEngineApi(engineType);
        GearboxApi gearbox = GearboxFactory.getGearbox(gearboxType);
        engineApi.run();
        gearbox.run();
    }
}

       客户端:

public class CarClient {
    public static void main(String[] args) {
        CarEngineer carEngineer = new CarEngineer();
        carEngineer.makeCar(1, 1);
    }
}

       运行结果:

/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/...
林肯发动机工作了
林肯变速箱工作了

       修改客户端carEngineer.makeCar(1, 2); 运行结果:

/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/...
林肯发动机工作了
丰田变速箱工作了

 1.1.2 问题        

       修改了产数之后,组装的汽车使用了林肯的发动机,而变速箱是丰田的,此时发动机与变速箱不是一个品牌,如果发动机与变速箱不匹配无法正常配合工作,那么组装的这个汽车就等于废了(这里假设只有同品牌的零部件才能正常配合动作)。

       显然发动机与变速箱是需要互相匹配,强依赖关系。就是选了这个发动机就必须选定某个变速箱。抽象工厂来解决这个问题。

       

 1.1.3 抽象工厂实现

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接又,而无需指定它们具体的类。

       解决1.1.2问题是要创建一序列有相互依赖关联和相互约束的产品——抽象工厂模式。

       代码改造

       发动机接口和变速箱接口不变:

public interface EngineApi {
    void run();
}
public interface GearboxApi {
    void run();
}

       发动机和变速箱的实现也不变:

public class LinkenEngineApiImpl implements EngineApi {
    @Override
    public void run() {
        System.out.println("林肯发动机工作了");
    }
}
public class LinkenGearboxApiImpl implements GearboxApi {
    @Override
    public void run() {
        System.out.println("林肯变速箱工作了");
    }
}
public class ToyotaEngineApiImpl implements EngineApi {
    @Override
    public void run() {
        System.out.println("丰田发动机工作了");
    }
}
public class ToyotaGearboxApiImpl implements GearboxApi {
    @Override
    public void run() {
        System.out.println("丰田变速箱工作了");
    }
}

       添加抽象工厂:(工厂抽象出来)

public interface AbstractFactory {
    /**
     * 创建发动机 <br/>
     */
    EngineApi createLinken();
    /**
     * 创建变速箱 <br/>
     */
    GearboxApi createGearbox();
}

       发动机工厂修改为林肯工厂,并实现抽象工厂:(//注释部分为简单工厂代码)

public class LinkenFactory implements AbstractFactory {
//public class EngineFactory {
    /**
     * 生产林肯发动机
     */
    @Override
    public EngineApi createLinken() {
        return new LinkenEngineApiImpl();
    }
    /**
     * 生产林肯发变速箱
     */
    @Override
    public GearboxApi createGearbox() {
        return new LinkenGearboxApiImpl();
    }
    //public static EngineApi getEngineApi(int i) {
    //    if (i == 1) {
    //        return new LinkenEngineApiImpl();
    //    }
    //
    //    return new ToyotaEngineApiImpl();
    //}
}

       变速箱工厂修改为丰田工厂,并实现抽象工厂:(//注释部分为简单工厂代码)

public class ToyotaFactory implements AbstractFactory {
//public class GearboxFactory {
    /**
     * 生产丰田发动机
     */
    @Override
    public EngineApi createLinken() {
        return new ToyotaEngineApiImpl();
    }
    /**
     * 生产丰田变事箱
     */
    @Override
    public GearboxApi createGearbox() {
        return new ToyotaGearboxApiImpl();
    }
    //public static GearboxApi getGearbox(int i) {
    //    if (1 == i) {
    //        return new LinkenGearboxApiImpl();
    //    }
    //
    //    return new ToyotaGearboxApiImpl();
    //}
}

        汽车组装类有修改:(//注释部分为简单工厂代码)

public class CarEngineer {
    /**
     * 接收选择好的哪一个序列产品工厂
     * @param factory
     */
    public void makeCar(AbstractFactory factory) {
        EngineApi engineApi = factory.createLinken();
        GearboxApi gearbox = factory.createGearbox();
        engineApi.run();
        gearbox.run();
    }
    //public void makeCar(int engineType, int gearboxType) {
    //    EngineApi engineApi = EngineFactory.getEngineApi(engineType);
    //    GearboxApi gearbox = GearboxFactory.getGearbox(gearboxType);
    //    engineApi.run();
    //    gearbox.run();
    //}
}

       客户端:(//注释部分为简单工厂代码)

public class CarClient {
    public static void main(String[] args) {
        //CarEngineer carEngineer = new CarEngineer();
        //carEngineer.makeCar(1, 2);
        CarEngineer carEngineer = new CarEngineer();
        // 传入选中的哪种产品工厂
        carEngineer.makeCar(new LinkenFactory());
    }
}

       运行结果:

/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/...
林肯发动机工作了
林肯变速箱工作了

       修改选中的产品工厂carEngineer.makeCar(new ToyotaFactory()) ,运行结果:

/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/...
丰田发动机工作了
丰田变速箱工作了

       这个抽象工厂相当于选择一套方案,方案确定好,里面的零件也就确定好了。不用一个零件一个零件的选择以免选择出错

       

二、模式讲解

2.1 功能

功能: 为一系列相关对象或相互依赖的对象创建一个接口。

接口内的方法是一系列相互依赖和约束的方法。

       

2.2 抽象工厂模式的结构及说明

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

       

2.3 示例代码程序结构图

       抽象工厂模式主要用于以下几个方面的应用场景中:

  1. 需要创建一系列相互依赖的对象:当一组对象之间存在依赖关系,并且需要保证这些对象是兼容的,抽象工厂模式可以用来创建这些对象的族群。
  2. 希望实现多个产品族的变化:抽象工厂模式允许你定义多个工厂类,每个工厂类可以创建不同的产品族,从而可以实现对产品族的变化。
  3. 需要切换产品组合:通过使用抽象工厂模式,可以很方便地切换不同的产品组合,而无需修改已有的客户端代码。

       优势方面,抽象工厂模式具有以下几个优势:

  1. 封装了对象的创建过程:客户端只需关注抽象工厂类和抽象产品类,而无需关心具体的创建细节,将对象创建的过程封装在工厂类中,提供了更高的封装性和抽象性。
  2. 符合开闭原则:抽象工厂模式对于新增新的产品族非常方便,只需创建对应的新的工厂类即可,并且不需要修改已有的代码,符合开闭原则。
  3. 保持产品族的一致性:通过抽象工厂模式创建的产品族中的产品具有一定的约束关系,保证了产品的一致性,避免了不兼容的产品组合。

       

2.4 抽象工厂模式与简单工厂模式

       抽象工厂模式和简单工厂模式是两种常见的设计模式,它们在对象的创建和管理上有一些不同之处。

 1. 目的和应用场景:

  • 简单工厂模式(Simple Factory Pattern)旨在根据给定的参数来创建单一类型的对象实例。它适用于需要根据条件创建不同类型的对象的情况,但它并没有分离对象的创建和使用,违反了单一职责原则。
  • 抽象工厂模式(Abstract Factory Pattern)旨在创建一系列相关或相互依赖的对象,而无需显式指定其具体类。它适用于需要创建一组相关的产品对象,并且需要确保这些产品是兼容的情况。

 2. 结构与实现:

  • 简单工厂模式通常由一个工厂类通过静态方法来创建对象,客户端通过调用工厂类的方法并传入相应的参数来获得所需的对象。
  • 抽象工厂模式通常由一组抽象工厂和一组具体工厂类组成,每个具体工厂负责创建一组特定的产品。

 3. 灵活性与扩展性:

  • 简单工厂模式的灵活性相对较低,因为一旦需要添加新类型的产品,通常需要修改工厂类的静态方法。
  • 抽象工厂模式支持产品族的概念,可以非常容易地添加新的产品族,只需要新增对应的具体工厂类即可,而不需要修改客户端代码。

总的来说,简单工厂模式适用于需要创建单一类型的对象,并且可以根据条件动态地创建不同类型的对象。而抽象工厂模式适用于创建一系列相关或相互依赖的对象,并且需要确保这些对象是兼容的情况。在实际应用中,根据具体的需求和设计目标来选择合适的设计模式。

       

2.5 抽象工厂模式与工厂方法模式

       抽象工厂模式(Abstract Factory Pattern)和工厂方法模式(Factory Method Pattern)虽然同属于创建型设计模式,旨在解耦对象的创建和使用,但两者在目的、实现方式及应用场景上存在明显区别:

 1. 目的:

  • 工厂方法模式的目的是允许一个类在不知道将要创建的对象的具体类型的情况下,推迟其实例化到子类中进行。
  • 抽象工厂模式的目的是创建一系列相关或者相互依赖的对象,而不需要指定它们具体的类。

 2. 实现方式:

  • 工厂方法模式定义了一个用于创建对象的接口,但由子类决定实例化哪一个类。工厂方法让类的实例化推迟到子类中进行。
  • 抽象工厂模式提供了一个创建一系列相关或互相依赖对象的接口,而不需要指定它们具体的类。它通常包含多个工厂方法来创建一系列不同的产品。

3. 应用场景:

  • 工厂方法模式主要用于单一产品的创建情形,即客户端只需要一个产品,而具体哪个产品则由具体工厂类在运行时决定。
  • 抽象工厂模式适用于创建一组产品(产品族),这些产品设计成合作使用的,客户端需要多个产品对象,这些对象要按照一定的方式配合工作。

 4. 结构复杂度:

  • 工厂方法模式结构相对简单,每个具体工厂类只需要负责一个产品的创建。
  • 抽象工厂模式结构相对复杂,一个工厂类需要负责多个产品对象的创建,这些对象通常属于不同的类系列。

 5. 扩展难度:

  • 工厂方法模式较容易扩展,引入新的产品类型只需要添加相应的具体工厂类和产品类即可。
  • 抽象工厂模式相对难以扩展,如果需要添加新的产品系列,需修改抽象工厂的接口以及所有的实现类,这会违反开闭原则。

总之,工厂方法模式用于创建一个产品,而抽象工厂模式用于创建多个相互依赖或相互关联的产品族。在选择使用哪一个模式时,需要根据具体场景和设计需求去判断。

相关文章
|
6月前
|
设计模式 XML API
掌握工厂方法模式,打造灵活多变的软件生产线
本文深入探讨了工厂方法模式在软件开发中的应用与优势,帮助读者掌握这一设计模式,进而打造灵活多变的软件生产线。文章首先介绍了工厂方法模式的基本概念和原理,通过生动的例子解释了该模式如何在不修改代码的情况下创建不同对象。接着,文章详细分析了工厂方法模式的特点和优势,包括降低对象之间的耦合度、提高系统的可扩展性和可维护性等。最后,文章结合实际案例,阐述了如何在项目中运用工厂方法模式来构建高效、灵活的软件架构。本文内容深入浅出,既适合初学者入门学习,也能为有经验的开发者提供有价值的参考。通过掌握工厂方法模式,您将能够更有效地应对软件开发中的挑战,实现更优质的软件产品。
80 2
|
6月前
|
前端开发 JavaScript Java
面向对象编程的艺术:构建高效可扩展的软件
面向对象编程的艺术:构建高效可扩展的软件
面向对象编程的艺术:构建高效可扩展的软件
|
算法 测试技术 数据安全/隐私保护
规则引擎算法的魅力:文档管理软件的灵活性与可扩展性
数字时代已经来了,文档管理软件已经成了企业和组织的宠儿。它们不仅能够帮你打理一大堆文档和信息,还能让你的工作效率飙升,减少犯错的机会,而且信息查找和分享也变得飞快。但是,随着各种各样的需求一直在不停地增长和变化,这些软件也要不停地充电升级,以满足用户们的新愿望。规则引擎算法在这方面可是大有作为,尤其是在让软件更灵活、更能扩展方面,它功不可没。接下来就让我们来看看规则引擎算法在文档管理软件中有哪些作用——
219 1
|
6月前
|
中间件 编译器 调度
嵌入式软件架构基础设施设计方法
嵌入式软件架构基础设施设计方法
164 0
|
6月前
|
Java 大数据 Android开发
探索Java编程语言的优势和应用领域
Java是一种广泛应用于软件开发领域的高级编程语言。它凭借其强大的功能和丰富的生态系统,在众多应用领域中得到了广泛应用。本文将为您介绍Java的优势以及它在各个领域中的应用。
795 2
|
6月前
|
人工智能 数据库
2024年春《企业级应用软件设计与开发》在线说明
《企业级应用软件设计与开发》是2024年春季的在线课程,旨在为学习者提供深入的企业级应用软件设计和开发知识。该课程涵盖了广泛的主题,包括系统架构、数据库设计、用户界面开发和性能优化等关键领域。
|
开发框架 数据可视化 数据库
第一代软件系统架构
欢迎来到我们的 QML & C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。 在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。通过直观的编码和可重用的组件,我们能够迅速开发出丰富多样的界面效果和动画效果。同时,我们利用 QML 强大的集成能力,轻松将 C++ 的底层逻辑和数据模型集成到前端界面中。 在后端方面,我们使用 C++ 编写高性能的算法、数据处理和计算逻辑。C++ 是一种强大的编程语言,能够提供卓越的性能和可扩展性。我们的团队致力于优化代码,减少资
|
存储 算法 程序员
25【软件基础】面向对象分析与设计思想总结
`面向对象的本质`:通过对象之间的协作完成功能。
654 0
|
存储 算法 网络协议
嵌入式应用软件架构设计
嵌入式应用软件架构设计
|
存储 算法 物联网
嵌入式应用软件架构设计(下)
嵌入式应用软件架构设计