设计模式——工厂模式

设计模式------工厂模式

我们今天来接着学习工厂模式,如果还没有看过上一篇简单工厂模式的小伙伴可以点击这里:

https://blog.csdn.net/qq_67693066/article/details/137498851

什么叫工厂模式

工厂模式是一种设计模式,主要用于解决对象创建的问题,它提供了一个接口用于创建对象,但是让子类决定实例化哪一个类。工厂模式的核心思想是将对象的创建过程封装起来,使客户端不需要知道具体的产品类,只需关心接口即可。这样可以极大地减少代码间的耦合度,增强系统的灵活性和可扩展性。

根据抽象程度和创建对象的复杂度,工厂模式可以细分为以下几种:

  1. 简单工厂模式(Simple Factory)
    定义一个工厂类,根据传入的参数条件决定创建哪种产品类的实例。工厂类承担了实例化对象的责任,客户端只需调用工厂类的静态方法或实例方法获取所需产品。
  2. 工厂方法模式(Factory Method)
    定义一个创建对象的接口,但让子类决定实例化哪一个类。工厂方法使得一个类的实例化延迟到其子类。
  3. 抽象工厂模式(Abstract Factory)
    提供一个接口,用于创建相关或依赖对象家族的多个对象,而不需要指定具体类。它创建的是对象族,而不是单个对象,常用于系统中有多系列产品需要一起创建,且各系列产品间有一定的关联关系。

通过使用工厂模式,你可以:

  • 隐藏创建逻辑:客户端无需了解对象是如何创建的。
  • 实现依赖倒置原则:高阶模块不依赖于低阶模块的具体实现,而依赖于抽象。
  • 降低耦合度:新增产品时,无需修改原有代码,只需新增相应的工厂和产品类。
  • 便于扩展:当需要新增产品类型时,只需要新增一个产品类和对应的工厂实现即可。

其中简单工厂模式已经在上篇提及到了,我们来看看这三种工厂模式的区别:

三种工厂模式的区别

让我们用生活中的例子来通俗地解释这三种工厂模式:

  1. 简单工厂模式(Simple Factory)
    假设你是一家快餐店的经理,店里卖汉堡、热狗和披萨。顾客来了只告诉你要吃什么,你(扮演工厂角色)负责根据顾客的要求准备食物。简单工厂就像是你这位经理,顾客说"我要一份汉堡",你就亲自去厨房做出一个汉堡给顾客。

在代码中,简单工厂就是一个静态方法或类,接收一个参数(比如食物类型),然后根据这个参数创建并返回一个相应的产品对象。

  1. 工厂方法模式(Factory Method)
    继续上面的例子,随着业务扩大,你决定开连锁店。这次,每个分店的经理不再需要亲自做汉堡,而是招聘了专门的厨师来做。你制定了一个规定:"每家分店都必须有一个'制作食物'的方法,但具体做什么食物由分店自己决定。"这就像是工厂方法模式,你定义了一个接口(抽象工厂类),要求每个分店(子类)都实现一个"制作食物"的方法,每个分店可以根据当地特色自由决定做什么样的食物。

在代码中,工厂方法模式定义了一个抽象工厂接口,包含一个创建产品的方法,具体的子类会实现这个方法来创建特定的产品对象。

  1. 抽象工厂模式(Abstract Factory)
    后来,你的餐饮帝国发展得更大了,不仅有汉堡、热狗和披萨,还开始经营早餐和甜品。这时你需要一个机制既能创建主食,也能创建饮料和甜品,形成一套完整的餐点组合。于是你设立了中央厨房,这个厨房负责按照地区和时段提供整套菜单(比如美式早餐套装、英式下午茶套装)。这就是抽象工厂,它能创建一系列相关联或互相依赖的产品族。

在代码中,抽象工厂模式定义了一个接口或抽象类,这个接口可以生成一族相关的产品对象,比如一个餐厅抽象工厂可以创建主食工厂、饮料工厂和甜品工厂,每一种工厂又能创建具体的产品。

总结一下,简单工厂模式是集中处理对象创建,工厂方法模式是将对象创建的权利委托给了子类,而抽象工厂模式则关注于创建一组相关的产品对象,它们各有侧重点,适用于不同的应用场景。

工厂方法模式

下面这个例子可以帮助我们了解工厂方法模式:

我们有一个线上教学的班级,现在要给这个班级配置每节课的教学任务,任务的类型有

练习:exam ;家庭作业:homework ;视频:video

图文:text ;PPT:ppt ;考试:testpaper

请以工厂设计模式来设计该模块的代码应该怎么写。

要求符合:

  1. 开闭原则;
  2. 单一职责原则;
  3. 依赖倒置原则;
  4. 接口隔离原则;
  5. 里氏替换原则;

首先工厂方法会有四个部分:抽象任务+具体任务+抽象工厂+具体工厂

cpp 复制代码
//抽象任务
class Task
{

};
//具体任务
//exam
class Exam : public Task
{

};

//Homework
class Homework : public Task
{

};

//video
class video : public Task
{

};

//text
class text : public Task
{

};


//ppt
class ppt : public Task
{

};

//ppt
class testpaper : public Task
{

};

//抽象工厂
class abstractFactory
{

};


//具体工厂
class realFactory : public abstractFactory
{

};

之后调用具体工厂,我们就可以对应创建相应的类:

cpp 复制代码
// 客户端代码,使用抽象工厂
void configureLesson(const std::vector<std::string>& tasksTypes, abstractFactory& factory)
{
    std::vector<std::unique_ptr<Task>> lessonTasks;
    for (const auto& type : tasksTypes)
    {
        auto task = factory.createTask(type);
        lessonTasks.push_back(std::move(task));
    }

    for(int i = 0; i < lessonTasks.size(); i++)
    {
        std::cout<<lessonTasks[i]->getTask_name()<<std::endl;
        lessonTasks[i]->execte();
        std::cout<<std::endl;
    }
    // 分配任务给学生,执行任务等操作...
}

完整代码如下:

cpp 复制代码
// 导入必要的头文件
#pragma once
#include<iostream>
#include<cstring>
#include<memory>
#include<vector>

// 抽象任务接口类,定义了任务的基本属性和行为
class Task
{
public:
    // 虚拟析构函数,确保派生类能够正确析构
    virtual ~Task() {};

    // 纯虚函数,用于获取任务名称,所有派生类必须重写此方法
    virtual std::string getTask_name() const = 0;

    // 纯虚函数,用于执行任务,所有派生类必须重写此方法
    virtual void execte() const = 0;
};

// 具体任务类,分别代表不同的任务类型
// Exam(考试任务)
class Exam : public Task
{
public:
    std::string getTask_name() const override
    {
        return "Exam";
    }

    void execte() const override
    {
        std::cout << "doing exam" << std::endl;
    }
};

// Homework(家庭作业任务)
class Homework : public Task
{
public:
    std::string getTask_name() const override
    {
        return "Homework";
    }

    void execte() const override
    {
        std::cout << "doing Homework" << std::endl;
    }
};

// video(视频学习任务)
class video : public Task
{
public:
    std::string getTask_name() const override
    {
        return "video";
    }

    void execte() const override
    {
        std::cout << "doing video" << std::endl;
    }
};

// text(文本阅读任务)
class text : public Task
{
public:
    std::string getTask_name() const override
    {
        return "text";
    }

    void execte() const override
    {
        std::cout << "doing text" << std::endl;
    }
};

// ppt(演示文稿任务)
class ppt : public Task
{
public:
    std::string getTask_name() const override
    {
        return "ppt";
    }

    void execte() const override
    {
        std::cout << "doing ppt" << std::endl;
    }
};

// testpaper(试卷任务)
class testpaper : public Task
{
public:
    std::string getTask_name() const override
    {
        return "testpaper";
    }

    void execte() const override
    {
        std::cout << "doing testpaper" << std::endl;
    }
};

// 抽象工厂接口,定义了创建任务对象的方法
class abstractFactory
{
public:
    virtual ~abstractFactory() {};

    // 纯虚函数,根据传入的字符串类型创建对应的任务对象
    virtual std::unique_ptr<Task> createTask(const std::string& name) const = 0;
};

// 具体工厂类,实现了抽象工厂接口,根据不同类型创建具体任务对象
class realFactory : public abstractFactory
{
public:
    std::unique_ptr<Task> createTask(const std::string& type) const override
    {
        if (type == "Exam")
        {
            return std::make_unique<Exam>();
        }
        else if (type == "Homework")
        {
            return std::make_unique<Homework>();
        }
        else if (type == "video")
        {
            return std::make_unique<video>();
        }
        else
        {
            // 如果传入的任务类型不支持,则抛出异常
            throw std::invalid_argument("Unsupported task type.");
        }
    }
};

// 客户端代码,使用抽象工厂配置课程任务
void configureLesson(const std::vector<std::string>& tasksTypes, abstractFactory& factory)
{
    // 创建存放任务智能指针的容器
    std::vector<std::unique_ptr<Task>> lessonTasks;

    // 根据任务类型列表,通过工厂创建任务对象并加入容器
    for (const auto& type : tasksTypes)
    {
        auto task = factory.createTask(type);
        lessonTasks.push_back(std::move(task)); // 使用移动语义存储任务
    }

    // 执行并展示所有任务
    for (int i = 0; i < lessonTasks.size(); i++)
    {
        std::cout << lessonTasks[i]->getTask_name() << std::endl;
        lessonTasks[i]->execte();
        std::cout << std::endl;
    }

    // 此处省略了分配任务给学生的逻辑及其他操作...
}

这段代码定义了一个抽象任务接口 Task,并创建了多个具体任务类,同时使用了抽象工厂模式来根据字符串类型动态创建任务对象。在客户端代码中,通过抽象工厂创建了一系列任务,并执行了这些任务。这样做的好处是可以方便地扩展任务类型,同时保持客户端代码的简洁和独立于具体任务实现。

相关推荐
CocoaAndYy26 分钟前
设计模式-单例模式
单例模式·设计模式
一颗花生米。2 小时前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼2 小时前
Java基础-单例模式的实现
java·开发语言·单例模式
学习使我快乐012 小时前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
bobostudio19952 小时前
TypeScript 设计模式之【策略模式】
前端·javascript·设计模式·typescript·策略模式
通信仿真实验室3 小时前
(10)MATLAB莱斯(Rician)衰落信道仿真1
开发语言·matlab
勿语&3 小时前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
ok!ko6 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
吾爱星辰7 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer7 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin