【C++】—— 工厂模式详解

本文详细介绍了工厂模式的特点,包括其优势(如解耦、可维护性和扩展性)以及三种主要分类(简单工厂模式、工厂方法模式和抽象工厂模式)。通过实例展示了每种模式的使用方法和适用场景。
摘要由CSDN通过智能技术生成

目录

(一)工厂模式的特点

(二)工厂模式分类

1、简单工厂模式

2、工厂方法模式

3、抽象工厂模式

(三)总结与回顾


(一)工厂模式的特点

 1、优势

  • ⼯⼚模式是⼀种创建型设计模式, 它提供了⼀种创建对象的最佳⽅式;
  • 在⼯⼚模式中,我们创建对象时不会对上层暴露创建逻辑,⽽是通过使⽤⼀个共同结构来指向新创建的对象,以此实现创建-使⽤的分离。
2、缺点
尽管工厂模式在许多情况下是一种有用的设计模式,但它也有一些缺点需要考虑:
  • 除了原来的产品类和客户端代码外,还需要定义工厂接口具体工厂类等额外的类。这可能导致系统变得更加复杂,特别是当需要创建多个不同类型的对象时。
但是尽管工厂模式存在上述缺点,但在许多情况下它仍然是一种有用的设计模式。在实际应用中,我们需要权衡使用工厂模式带来的好处和缺点,并根据具体情况进行选择。

(二)工厂模式分类

工厂模式可以分为三种不同的类型:简单工厂模式工厂方法模式抽象工厂模式

1、简单工厂模式

简单⼯⼚模式实现由⼀个⼯⼚对象通过类型决定创建出来指定产品类的实例。
  • 假设有个⼯⼚能⽣产出⽔果,当客⼾需要产品的时候明确告知⼯⼚⽣产哪类⽔果,⼯⼚需要接收⽤⼾提供的类别信息,当新增产品的时候,⼯⼚内部去添加新产品的⽣产⽅式。
接下来,我们看代码演示:
#include<iostream>
#include <string>
#include <memory>

class Fruit{
    public:
        Fruit(){}
        virtual void show() = 0;
};
class Apple : public Fruit{
    public:
        Apple(){}
        virtual void show(){
            std::cout << "我是一个苹果" << std::endl;
        }
};

class Banana : public Fruit{
    public:
        Banana(){}
        virtual void show(){
            std::cout << "我是一个香蕉" << std::endl;
        }
};

class FruitFactory{
    public:
        static std::shared_ptr<Fruit> create(const std::string &name){
            if(name == "苹果"){
                return std::make_shared<Apple>();
            }
            else if(name == "香蕉"){
                return std::make_shared<Banana>();
            }
            else{
                return std::shared_ptr<Fruit>(); 
            }
        }
};
int main()
{
    std::shared_ptr<Fruit> fruit = FruitFactory::create("苹果");
    fruit->show();
    fruit = FruitFactory::create("香蕉");
    fruit->show();
    return 0;
}

运行结果如下:

【小结】
简单⼯⼚模式:通过参数控制可以⽣产任何产品

优点

  • 简单粗暴,直观易懂。使⽤⼀个⼯⼚⽣产同⼀等级结构下的任意产品
  缺点
  • 1. 所有东西⽣产在⼀起,产品太多会导致代码量庞⼤
  • 2. 开闭原则遵循(开放拓展,关闭修改)的不是太好,要新增产品就必须修改⼯⼚⽅法。

2、工厂方法模式

工厂方法模式定义一个创建对象的接口,但将实际的实例化延迟到子类中。每个子类都可以根据需要创建适合自身的对象。

  • 假设现在有A、B 两种产品,则开两个⼯⼚,⼯⼚ A 负责⽣产产品 A,⼯⼚ B 负责⽣产产品 B,⽤⼾只知道产品的⼯⼚名,⽽不知道具体的产品信息,⼯⼚不需要再接收客⼾的产品类别,⽽只负责⽣产产品。

接下来,我们还是看代码演示:

#include<iostream>
#include <string>
#include <memory>

class Fruit{
    public:
        Fruit(){}
        virtual void show() = 0;
};
class Apple : public Fruit{
    public:
        Apple(){}
        virtual void show(){
            std::cout << "我是一个苹果" << std::endl;
        }
};

class Banana : public Fruit{
    public:
        Banana(){}
        virtual void show(){
            std::cout << "我是一个香蕉" << std::endl;
        }
};


//工厂模式方法

class FruitFactory{
    public:
        virtual std::shared_ptr<Fruit> create() = 0;
};

class AppleFactory : public FruitFactory{
    public:
        virtual std::shared_ptr<Fruit> create(){
            return std::make_shared<Apple>();
        }
};

class BananaFactory : public FruitFactory{
    public:
        virtual std::shared_ptr<Fruit> create(){
            return std::make_shared<Banana>();
        }
};

int main()
{
    std::shared_ptr<FruitFactory> factory(new AppleFactory());
    std::shared_ptr<Fruit> fruit = factory->create();
    fruit->show();
    factory.reset(new BananaFactory());
    fruit = factory->create();
    fruit->show();
    return 0;
}

运行结果如下:

【小结】

⼯⼚⽅法:定义⼀个创建对象的接⼝,但是由⼦类来决定创建哪种对象,使⽤多个⼯⼚分别⽣产指定 的固定产品
优点
  • 1. 减轻了⼯⼚类的负担,将某类产品的⽣产交给指定的⼯⼚来进⾏
  • 2. 开闭原则遵循较好,添加新产品只需要新增产品的⼯⼚即可,不需要修改原先的⼯⼚类
缺点
  • 对于某种可以形成⼀组产品族的情况处理较为复杂,需要创建⼤量的⼯⼚类

⼯⼚⽅法模式通过引⼊⼯⼚等级结构,解决了简单⼯⼚模式中⼯⼚类职责太重的问题,但由于⼯⼚⽅法模式中的每个⼯⼚只⽣产⼀类产品,可能会导致系统中存在⼤量的⼯⼚类,势必会增加系统的开销。———— 由此就引入了抽象工厂模式。


3、抽象工厂模式

可以考虑将⼀些相关的产品组成⼀个产品族(位于不同产品等级 结构中功能相关联的产品组成的家族),由同⼀个⼯⼚来统⼀⽣产,这就是抽象⼯⼚模式的基本思想。

接下来,我们还是看代码演示:

#include<iostream>
#include <string>
#include <memory>

//产品类一:水果
class Fruit{
    public:
        Fruit(){}
        virtual void show() = 0;
};
class Apple : public Fruit{
    public:
        Apple(){}
        virtual void show(){
            std::cout << "我是一个苹果" << std::endl;
        }
};

class Banana : public Fruit{
    public:
        Banana(){}
        virtual void show(){
            std::cout << "我是一个香蕉" << std::endl;
        }
};


//产品类二:动物
class Animal {
    public:
        virtual void voice() = 0;
};

class Lamp: public Animal {
    public:
        void voice() override { std::cout << "咩咩咩\n"; }
};

class Dog: public Animal {
    public:
        void voice() override { std::cout << "汪汪汪\n"; }
};


class Factory {
    public:
        virtual std::shared_ptr<Fruit> getFruit(const std::string &name) = 0;
        virtual std::shared_ptr<Animal> getAnimal(const std::string &name) = 0;
};

class FruitFactory : public Factory {
    public:
        virtual std::shared_ptr<Animal> getAnimal(const std::string &name) {
            return std::shared_ptr<Animal>();
        }
    virtual std::shared_ptr<Fruit> getFruit(const std::string &name) {
        if (name == "苹果") {
            return std::make_shared<Apple>();
        }else if(name == "⾹蕉") {
            return std::make_shared<Banana>();
        }
        return std::shared_ptr<Fruit>();
    }
};

class AnimalFactory : public Factory {
    public:
        virtual std::shared_ptr<Fruit> getFruit(const std::string &name) {
            return std::shared_ptr<Fruit>();
        }
        virtual std::shared_ptr<Animal> getAnimal(const std::string &name) {
            if (name == "⼩⽺") {
                return std::make_shared<Lamp>();
            }else if(name == "⼩狗") {
                return std::make_shared<Dog>();
            }
            return std::shared_ptr<Animal>();
        }
};


class FactoryProducer {
    public:
        static std::shared_ptr<Factory> getFactory(const std::string &name) {
            if (name == "动物") {
                return std::make_shared<AnimalFactory>();
            }else {
                return std::make_shared<FruitFactory>();
            }   
        }
};


int main()
{
    std::shared_ptr<Factory> fruit_factory = FactoryProducer::getFactory("⽔果");
    std::shared_ptr<Fruit> fruit = fruit_factory->getFruit("苹果");
    fruit->show();
    fruit = fruit_factory->getFruit("⾹蕉");
    fruit->show();

    std::shared_ptr<Factory> animal_factory = FactoryProducer::getFactory("动物");
    std::shared_ptr<Animal> animal = animal_factory->getAnimal("⼩⽺");
    animal->voice();
    animal = animal_factory->getAnimal("⼩狗");
    animal->voice();

    return 0;
}

运行结果如下:

【小结】

抽象⼯⼚:围绕⼀个超级⼯⼚创建其他⼯⼚。每个⽣成的⼯⼚按照⼯⼚模式提供对象。

抽象⼯⼚模式适⽤于⽣产多个⼯⼚系列产品衍⽣的设计模式,增加新的产品等级结构复杂,需要对原有系统进⾏较⼤的修改,甚⾄需要修改抽象层代码,违背了“开闭原则”。

 


(三)总结与回顾

以上便是本文关于工厂模式的全部内容,接下来简单回顾总结下本文都讲到了什么!!!

工厂模式是一种创建型设计模式,旨在封装对象的实例化过程,使得客户端代码与具体类的实例化过程解耦,从而提高代码的可维护性、可扩展性和灵活性;

优势:

  1. 解耦: 工厂模式能够将对象的创建和使用分离,降低了客户端与具体类之间的耦合度。

  2. 可维护性: 当需要修改或扩展具体类时,只需修改工厂类而不影响客户端代码,提高了系统的可维护性。

  3. 扩展性: 可通过增加新的具体工厂和具体产品来扩展系统,符合开闭原则。

  4. 代码复用: 工厂模式促进了代码的复用,因为客户端通过接口或基类与工厂类交互,而不直接与具体类交互。

适用场景:

  1. 对象的创建逻辑复杂: 当对象的创建涉及一系列复杂的步骤或条件判断时,使用工厂模式可以将这些复杂性封装起来。

  2. 需要根据条件动态创建对象: 当需要根据不同条件来创建不同类型的对象时,工厂模式是一个有效的选择。

  3. 系统需要更高的灵活性和可扩展性: 工厂模式允许系统在不修改客户端代码的情况下引入新的产品类和工厂类,提供了系统的可扩展性。

到此,本文的内容全部讲解结束。感谢大家的观看与支持!!!

 

 

  • 34
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

起飞的风筝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值