C++ 【抽象工厂】

基础理解

Q:抽象工厂与简单工厂有什么不同
A:抽象工厂适用于一个产品下面有许多具体的子产品,而简单工厂则是只有一个单一的产品。所以抽象工厂在使用中会多一些。

Q:抽象工厂的应用场景
A:首先你要懂得简单工厂的思路用法,如果你需要与多个不同系列(椅子,沙发)的相关产品(维多利亚,现代)交互, 但是由于无法提前获取具体产品类 (现代椅子 ), 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建,在这种情况下, 你可以使用抽象工厂。
跳转观看简单工厂

注意点

  1. 兼容性:确保由同一抽象工厂创建的所有产品都是兼容的,并且可以系统中无缝地进行交互和替换。
  2. 管理变体:确保每个变体都有对应的工厂,并且工厂创建的产品能够符合该变体的特性和要求。
  3. 足够抽象:遵循循依赖倒置原则,即高层模块不应该依赖于具体的实现细节,而应该依赖于抽象

在我下面写的代码中,ClientCode(客户端) 依赖于抽象类(抽象工厂AbstractFactory) 不具体依赖于是维多利亚工厂 或 现代工厂

创建抽象工厂

例如我们有:

  1. 椅子种类:维多利亚椅子 现代椅子…
  2. 沙发种类:维多利亚沙发 现代沙发…

拆分一下椅子种类
椅子抽象类拆分具体类
我们需要声明抽象工厂(AbstractFactory)——包含系列中所有产品构造方法的接口:Creat_ChairCreat_Sofa
基于抽象工厂类创建 具体分支的工厂:维多利亚工厂现代工厂 (维多利亚工厂只能创建维多利亚椅子,和维多利亚沙发)
有什么好用的画图软件推荐一下吗?我这个鬼软件复制vscode 的代码就变黑了

UML图

看个大体,明白之间的关系即可
空心箭头:继承关系
虚线箭头:依赖
实线箭头:关联
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
/**
产品家族的每个不同产品都应该有一个基础接口。产品的所有变体都必须实现这个接口。
 */

class Chair
{
public:
    virtual ~Chair(){};
    virtual std::string name() const = 0;
};

class VictorianChair : public Chair
{
public:
    std::string name() const override
    {
        return "维多利亚椅子\n";
    }
};

class ModernChair : public Chair
{
    std::string name() const override
    {
        return "现代椅子\n";
    }
};

/**
 这是另一个产品的基础接口。所有产品可以相互交互,但是只有相同具体变体的产品之间才可能进行适当的交互。
 */
class Sofa
{
public:
    virtual ~Sofa(){};
    virtual std::string name() const = 0;
    /**
     * ...但它也可以与Chair合作。
     * 抽象工厂确保其创建的所有产品都属于同一变体,因此是相容的。
     */
    virtual std::string combination(const Chair &collaborator) const = 0; // combination:组合
};

/**
 *维多利亚产品由相应的维多利亚工厂生产。
 */
class VictorianSofa : public Sofa
{
public:
    std::string name() const override
    {
        return "维多利亚沙发\n";
    }
    /**
    变体 维多利亚沙发只能与变体 维多利亚椅子 正确地配合使用。然而,它可以接受任何 椅子Chair 的实例作为参数。

   */
    std::string combination(const Chair &collaborator) const override
    {
        const std::string result = collaborator.name();
        return "给你送来 维多利亚沙发 和  " + result + " ";
    }
};

class ModernSofa : public Sofa
{
public:
    std::string name() const override
    {
        return "现代沙发\n";
    }

    std::string combination(const Chair &collaborator) const override
    {
        const std::string result = collaborator.name();
        return "给你送来 现代沙发 和 " + result + " ";
    }
};
/**
抽象工厂接口声明了一组方法,这些方法返回不同的抽象产品。这些产品被称为一个家族,它们之间由一个高层次的主题或概念相关联。一个产品家族可能有几个变体,但一个变体的产品与另一个变体的产品不兼容。
*/
class AbstractFactory
{
public:
    virtual Chair *Creat_Chair() const = 0;
    virtual Sofa *Creat_Sofa() const = 0;
};

/**
具体工厂生产属于单个变体的产品家族。工厂确保生成的产品是相容的。请注意,具体工厂方法的签名返回一个抽象产品,而在方法内部实例化一个具体产品。
*/
class VictorianFactory : public AbstractFactory
{
public:
    Chair *Creat_Chair() const override
    {
        return new VictorianChair();
    }
    Sofa *Creat_Sofa() const override
    {
        return new VictorianSofa();
    }
};

class ModernFactory : public AbstractFactory
{
public:
    Chair *Creat_Chair() const override
    {
        return new ModernChair();
    }
    Sofa *Creat_Sofa() const override
    {
        return new ModernSofa();
    }
};

/**
客户端代码只通过抽象类型 抽象工厂 和 抽象产品(椅子,沙发) 与工厂和产品进行交互。这样可以在不破坏客户端代码的情况下传递任何工厂或产品的子类。
 */

void ClientCode(const AbstractFactory &factory)
{
    const Chair *product_a = factory.Creat_Chair();
    const Sofa *product_b = factory.Creat_Sofa();
    std::cout << product_b->name() << "\n";
    std::cout << product_b->combination(*product_a) << "\n";
    delete product_a;
    delete product_b;
}

int main()
{
    std::cout << "Client: 测试维多利亚工厂:\n";
    VictorianFactory *f1 = new VictorianFactory();
    ClientCode(*f1);
    delete f1;
    std::cout << std::endl;
    std::cout << "Client: 测试现代工厂:\n";
    ModernFactory *f2 = new ModernFactory();
    ClientCode(*f2);
    delete f2;

    system("pause");
    return 0;
}

优缺点

优点缺点
确保同一工厂生成的产品相互匹配。采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。
避免客户端和具体产品代码的耦合。
单一职责原则。 同一种类的产品生成代码在到同一位置, 易于维护。
开闭原则。 引入新产品变体时, 无需修改客户端代码。

与其他模式的关系

  1. 抽象工厂可以用单例模式来实现。(只存在一个抽象工厂)
  2. 设计工作的初期都会使用 简单工厂 (较为简单, 而且可以更方便地通过子类进行定制), 随后演化为使用抽象工厂模式(更灵活但更加复杂)。
  3. 抽象工厂模式通常基于一组工厂方法, 但你也可以使用原型模式来生成这些类的方法。

原型工厂方法模式中,工厂方法不是直接创建产品的新实例,而是基于现有的原型(Prototype)对象创建新的产品实例。这种方式可以在需要创建新实例时避免耗费资源来实例化新对象,而是通过复制现有对象来创建新实例。

  1. 当只需对客户端代码隐藏子系统创建对象的方式时, 你可以使用抽象工厂来代替外观模式。(外观模式是隐藏整个代码)
  2. 你可以将抽象工厂和桥接模式搭配使用。 如果由桥接定义的抽象只能与特定接口API实现合作。(当这个抽象使用这个工厂,就会生产出符合这个抽象所需要的具体接口API)
    在这里插入图片描述
    如果有错还望指正。谢谢大家。
    参考文章
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值