当前位置: 首页 > news >正文

「软件设计模式」工厂方法模式 vs 抽象工厂模式

前言

在软件工程领域,设计模式是解决常见问题的经典方案。本文将深入探讨两种创建型模式:工厂方法模式抽象工厂模式,通过理论解析与实战代码示例,帮助开发者掌握这两种模式的精髓。


一、工厂方法模式(Factory Method Pattern)

1.1 模式思想

工厂方法模式的核心在于将对象的创建延迟到子类,通过定义创建对象的接口,让子类决定实例化哪个类。这种模式完美体现了依赖倒置原则

1.2 模式结构

  • Product:抽象产品接口
  • ConcreteProduct:具体产品实现
  • Creator:抽象创建者
  • ConcreteCreator:具体创建者

1.3 代码示例

#include <iostream>
#include <string>

class Shape {
public:
    virtual void draw() = 0;
};

class Circle : public Shape {
    void draw() {
        std::cout << "Circle::draw()" << std::endl;
    }
};

class Rectangle : public Shape {
    void draw() {
        std::cout << "Rectangle::draw()" << std::endl;
    }
};

class Square : public Shape {
    void draw() {
        std::cout << "Square::draw()" << std::endl;
    }
};

class ShapeFactory {
public:
    Shape* getShape(const std::string& shapeType) {
        if (shapeType.empty()) {
            return nullptr;
        }

        if (shapeType == "CIRCLE") {
            return new Circle();
        } else if (shapeType == "RECTANGLE") {
            return new Rectangle();
        } else if (shapeType == "SQUARE") {
            return new Square();
        }

        return nullptr;
    }
};
#include "factory_mode.h"

int main(int argc, char const* argv[]) {
    ShapeFactory* shapeFactory = new ShapeFactory();
    Shape* shape1 = shapeFactory->getShape("CIRCLE");
    shape1->draw();
    Shape* shape2 = shapeFactory->getShape("RECTANGLE");
    shape2->draw();
    Shape* shape3 = shapeFactory->getShape("SQUARE");
    shape3->draw();
    delete shapeFactory;
    return 0;
}

1.4 运行结果

1.5 适用场景

  • 需要灵活扩展产品类型
  • 创建过程需要封装处理逻辑
  • 需要解耦客户端与具体产品类

二、抽象工厂模式(Abstract Factory Pattern)

2.1 模式思想

抽象工厂模式通过创建相关对象族来提升系统的扩展性,强调产品系列的概念。它比工厂方法模式更高层次的抽象。

2.2 模式结构

  • AbstractFactory:抽象工厂接口
  • ConcreteFactory:具体工厂实现
  • AbstractProduct:抽象产品接口
  • ConcreteProduct:具体产品实现

2.3 代码示例

产品定义:

#include <iostream>
#include <string>
// 
class Color {
public:
    virtual void fill() = 0;
};

class Red : public Color {
public:
    void fill() {
        std::cout << "Red::fill()" << std::endl;
    }
};

class Green : public Color {
public:
    void fill() {
        std::cout << "Green::fill()" << std::endl;
    }
};

class Blue : public Color {
public:
    void fill() {
        std::cout << "Blue::fill()" << std::endl;
    }
};
// 形状产品
class Shape {
public:
    virtual void draw() = 0;
};

class Circle : public Shape {
    void draw() {
        std::cout << "Circle::draw()" << std::endl;
    }
};

class Rectangle : public Shape {
    void draw() {
        std::cout << "Rectangle::draw()" << std::endl;
    }
};

class Square : public Shape {
    void draw() {
        std::cout << "Square::draw()" << std::endl;
    }
};

 抽象工厂

#include "color.h"
#include "shape.h"
// 抽象工厂
class AbstractFactory {
public:
    virtual Shape* getShape(const std::string& shapeType) = 0;
    virtual Color* getColor(const std::string& colorType) = 0;
};

 实体工厂

#include "abstract_factory.h"
// 实体工厂类

// 形状工厂
class ShapeFactory : public AbstractFactory {
public:
    Shape* getShape(const std::string& shapeType) {
        if (shapeType.empty()) {
            return nullptr;
        }

        if (shapeType == "CIRCLE") {
            return new Circle();
        } else if (shapeType == "RECTANGLE") {
            return new Rectangle();
        } else if (shapeType == "SQUARE") {
            return new Square();
        }

        return nullptr;
    }

    Color* getColor(const std::string& colorType) {
        return nullptr;
    }
};

// 颜色工厂
class ColorFactory : public AbstractFactory {
public:
    Color* getColor(const std::string& colorType) {
        if (colorType.empty()) {
            return nullptr;
        }

        if (colorType == "RED") {
            return new Red();
        } else if (colorType == "GREEN") {
            return new Green();
        } else if (colorType == "BLUE") {
            return new Blue();
        }

        return nullptr;
    }
    Shape* getShape(const std::string& shapeType) {
        return nullptr;
    }
};

 生产商:

#include "factory.h"

class FactoryProducer {
public:
    static AbstractFactory* getFactory(const std::string& choice) {
        if (choice == "SHAPE") {
            return new ShapeFactory();
        } else if (choice == "COLOR") {
            return new ColorFactory();
        }
        return nullptr;
    }
};

main:

#include "producer.h"

// 抽象工厂 demo
int main(int argc, char const* argv[]) {
    AbstractFactory* shapeFactory = FactoryProducer::getFactory("SHAPE");
    Shape* shape1 = shapeFactory->getShape("CIRCLE");
    shape1->draw();
    Shape* shape2 = shapeFactory->getShape("RECTANGLE");
    shape2->draw();
    Shape* shape3 = shapeFactory->getShape("SQUARE");
    shape3->draw();
    AbstractFactory* colorFactory = FactoryProducer::getFactory("COLOR");
    Color* color1 = colorFactory->getColor("RED");
    color1->fill();
    Color* color2 = colorFactory->getColor("GREEN");
    color2->fill();
    Color* color3 = colorFactory->getColor("BLUE");
    color3->fill();
    delete shapeFactory;
    delete colorFactory;
    return 0;
}

2.4 运行结果

2.5 适用场景

  • 需要创建多个相关对象组成的系列
  • 系统需要支持不同产品族的切换
  • 产品对象之间存在约束关系

三、核心差异对比

维度工厂方法模式抽象工厂模式
抽象层次单个产品创建产品族创建
扩展方向垂直扩展(新增产品类型)水平扩展(新增产品族)
实现方式继承组合
系统复杂度简单复杂
典型应用场景日志记录器、支付方式跨平台UI组件、数据库访问

四、模式选择指南

  • 选择工厂方法模式当:

    • 需要解耦客户端与具体产品类
    • 系统需要支持多种同类产品的创建
    • 产品类型相对单一
  • 选择抽象工厂模式当:

    • 需要创建多个相互关联的产品
    • 需要保证产品之间的兼容性
    • 系统需要支持不同产品族的切换

五、最佳实践建议

  1. 优先使用工厂方法:当产品结构简单时,避免过度设计
  2. 注意开闭原则:通过扩展而非修改来增加新产品
  3. 使用依赖注入:结合Spring等框架实现更灵活的工厂管理
  4. 文档化产品族:明确各产品之间的约束关系
  5. 性能考量:复杂工厂实现需要考虑对象池等优化手段

结语

        掌握工厂模式是成为架构师的重要阶梯。工厂方法模式像专业工匠,专注单一产品的精雕细琢;抽象工厂模式如生产总监,统筹协调整个产品家族。理解它们的差异,才能在系统设计中做出最合适的选择。 

相关文章:

  • Linux 内核架构入门:从基础概念到面试指南*
  • 《Stable Diffusion绘画完全指南:从入门到精通的Prompt设计艺术》 第三章
  • 【前端框架与库】「深入理解 Vue 插槽」:类型、用法与实际场景解析,增强组件复用性的利器
  • 【力扣题解】【76. 最小覆盖子串】容易理解版
  • 进程等待与进程替换
  • LeetCode每日精进:876.链表的中间结点
  • 本地部署DeepSeek-R1模型(新手保姆教程)
  • Elasticsearch:15 年来致力于索引一切,找到重要内容
  • kubernetes源码分析 kubelet
  • k8s启空容器用于排查问题
  • OpenCV机器学习(1)人工神经网络 - 多层感知器类cv::ml::ANN_MLP
  • 伯克利 CS61A 课堂笔记 08 —— Strings and Dictionaries
  • RunLoop 详解
  • 浏览器自动化与AI Agent结合项目browser-use初探
  • 【虚幻引擎UE】UE4.23到UE5.5的核心功能变化
  • 2. grafana插件安装并接入zabbix
  • 数据结构:数组
  • 【微服务学习一】springboot微服务项目构建以及nacos服务注册
  • Android adb测试常用命令大全
  • 数据结构之队列,哈希表
  • 丰富“互换通”产品类型,促进中国金融市场高水平对外开放
  • 李家超:明日起香港特区护照持有人可免签入境阿联酋
  • 《歌手2025》公布首发阵容,第一期就要淘汰一人
  • 乌总统:若与普京会谈,全面停火和交换战俘是主要议题
  • 美国明尼苏达州发生山火,过火面积超80平方公里
  • 外企聊营商|波音速度:创新审批促“起飞”