抽象工厂模式(Abstract Factory)

这篇具有很好参考价值的文章主要介绍了抽象工厂模式(Abstract Factory)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

定义

抽象工厂是一种创建型设计模式,它能创建一系列相关的对象,而无需指定其具体类

前言

1. 问题

假设你正在开发一款家具商店模拟器。你的代码中包括一些类,用于表示:

  • 一系列相关产品,例如椅子(Chair)、沙发(Sofa)和咖啡桌(CoffeeTable)
  • 系列产品的不同变体,例如你可以使用现代(Modern)、维多利亚(Victorian)和装饰风艺术(ArtDeco)等风格生成这些产品

抽象工厂模式(Abstract Factory)

你需要设法单独生成每件家具对象,这样才能确保其风格一致。如果顾客收到的家具风格不一样,他们可不会开心。

此外, 你也不希望在添加新产品或新风格时修改已有代码。家具供应商对于产品目录的更新非常频繁,你不会想在每次更新时都去修改核心代码的。

2. 解决方案

首先,抽象工厂模式建议为系列中的每件产品明确声明接口(例如椅子、沙发或咖啡桌)。然后,确保所有产品变体都继承这些接口。例如,所有风格的椅子都实现椅子接口;所有风格的咖啡桌都实现咖啡桌接口,以此类推。

抽象工厂模式(Abstract Factory)

接下来, 我们需要声明抽象工厂——包含系列中所有产品构造方法的接口。例如创建椅子(createChair)、创建沙发(createSofa)和 创建咖啡桌(createCoffeeTable)。这些方法必须返回抽象产品类型,即我们之前抽取的那些接口: 椅子,沙发和咖啡桌等等。

抽象工厂模式(Abstract Factory)

那么该如何处理产品变体呢? 对于系列产品的每个变体, 我们都将基于抽象工厂接口创建不同的工厂类。每个工厂类都只能返回特定类别的产品,例如, 现代家具工厂(ModernFurnitureFactory)只能创建现代椅(ModernChair)、现代沙发(ModernSofa)和现代咖啡桌(ModernCoffeeTable)对象。

客户端代码可以通过相应的抽象接口调用工厂和产品类。你无需修改实际客户端代码,就能更改传递给客户端的工厂类,也能更改客户端代码接收的产品变体。

假设客户端想要工厂创建一把椅子。客户端无需了解工厂类,也不用管工厂类创建出的椅子类型。无论是现代风格,还是维多利亚风格的椅子,对于客户端来说没有分别,它只需调用抽象椅子接口就可以了。这样一来,客户端只需知道椅子以某种方式实现了坐下(sitOn)方法就足够了。此外,无论工厂返回的是何种椅子变体,它都会和由同一工厂对象创建的沙发或咖啡桌风格一致。

最后一点说明:如果客户端仅接触抽象接口,那么谁来创建实际的工厂对象呢?一般情况下,应用程序会在初始化阶段创建具体工厂对象。而在此之前,应用程序必须根据配置文件或环境设定选择工厂类别。

结构

抽象工厂模式(Abstract Factory)

  1. 抽象产品(Abstract Product)为构成系列产品的一组不同但相关的产品声明接口。
  2. 具体产品(Concrete Product)是抽象产品的多种不同类型实现。所有变体(维多利亚/现代)都必须实现相应的抽象产品(椅子/沙发)。
  3. 抽象工厂(Abstract Factory)接口声明了一组创建各种抽象产品的方法。
  4. 具体工厂(Concrete Factory)实现抽象工厂的构建方法。每个具体工厂都对应特定产品变体,且仅创建此种产品变体。
  5. 尽管具体工厂会对具体产品进行初始化,其构建方法签名必须返回相应的抽象产品。这样,使用工厂类的客户端代码就不会与工厂创建的特定产品变体耦合。客户端(Client)只需通过抽象接口调用工厂和产品对象,就能与任何具体工厂/产品变体交互。

适用场景

  • 如果代码需要与多个不同系列的相关产品交互,但是由于无法提前获取相关信息,或者出于对未来扩展性的考虑,你不希望代码基于产品的具体类进行构建,在这种情况下,你可以使用抽象工厂。

抽象工厂为你提供了一个接口,可用于创建每个系列产品的对象。只要代码通过该接口创建对象,那么你就不会生成与应用程序已生成的产品类型不一致的产品。

  • 如果你有一个基于一组抽象方法的类,且其主要功能因此变得不明确,那么在这种情况下可以考虑使用抽象工厂模式。

在设计良好的程序中,每个类仅负责一件事。如果一个类与多种类型产品交互,就可以考虑将工厂方法抽取到独立的工厂类或具备完整功能的抽象工厂类中。

实现方式

  1. 以不同的产品类型与产品变体为维度绘制矩阵。
  2. 为所有产品声明抽象产品接口。然后让所有具体产品类实现这些接口。
  3. 声明抽象工厂接口,并且在接口中为所有抽象产品提供一组构建方法。
  4. 为每种产品变体实现一个具体工厂类。
  5. 在应用程序中开发初始化代码。该代码根据应用程序配置或当前环境,对特定具体工厂类进行初始化。然后将该工厂对象传递给所有需要创建产品的类。
  6. 找出代码中所有对产品构造函数的直接调用,将其替换为对工厂对象中相应构建方法的调用。

优点

  • 你可以确保同一工厂生成的产品相互匹配。
  • 你可以避免客户端和具体产品代码的耦合。
  • 单一职责原则。你可以将产品生成代码抽取到同一位置,使得代码易于维护。
  • 开闭原则。向应用程序中引入新产品变体时,你无需修改客户端代码。

缺点

由于采用该模式需要向应用中引入众多接口和类,代码可能会比之前更加复杂。

实例

AbstractFactory.hpp

#ifndef A2AC74A4_E96A_4B51_937C_1E888FCCF4EC
#define A2AC74A4_E96A_4B51_937C_1E888FCCF4EC

#include <memory>
#include "AbstractProduct.hpp"

class Factory{
    public:
        virtual shared_ptr<Movie> productMovie()=0;
        virtual shared_ptr<Book> productBook() = 0;
};

#endif /* A2AC74A4_E96A_4B51_937C_1E888FCCF4EC */

 ConcreteFactory.hpp


#ifndef B6D4A87E_8B55_4433_9446_CD0A4E05F3EB
#define B6D4A87E_8B55_4433_9446_CD0A4E05F3EB

#include "AbstractFactory.hpp"
#include "AbstractProduct.hpp"
#include "ConcreteProduct.hpp"
#include <memory>
using namespace std;

class ChineseProduct: public Factory{
    public:
        shared_ptr<Movie> productMovie() override{
            return make_shared<ChineseMovie>();
        }
        shared_ptr<Book> productBook() override{
            return make_shared<ChineseBook>();
        }
};

class JapaneseProduct : public Factory{
    public:
        shared_ptr<Movie> productMovie()override{
            return make_shared<JapaneseMovie>();
        }
        shared_ptr<Book> productBook() override{
            return make_shared<JapaneseBook>();
        }
};


#endif /* B6D4A87E_8B55_4433_9446_CD0A4E05F3EB */

AbstractProduct.hpp

#ifndef B7A6F158_17F4_48CB_864F_79A6515F2190
#define B7A6F158_17F4_48CB_864F_79A6515F2190

#include <string>
using namespace std; 

class Movie{
    public:
        virtual string showMoiewName() = 0;
};
class Book{
    public :
        virtual string showBookName() = 0;
};
#endif /* B7A6F158_17F4_48CB_864F_79A6515F2190 */

ConcreteProduct.hpp

#ifndef C0BF2BA5_C17A_4007_B403_C5CCB379961C
#define C0BF2BA5_C17A_4007_B403_C5CCB379961C

#include <string>
#include <iostream>
#include "AbstractProduct.hpp"

class ChineseMovie : public Movie {
    string showMoiewName() override {
        return "让子弹飞";
    }
};
class JapaneseMovie : public Movie{
    string showMoiewName() override {
        return "千与千寻";
    }
};

class ChineseBook : public Book{
    string showBookName override {
        return "三国演义";
    }
};
class JapaneseBook : public Book{
    string showBookName() override {
        return "白夜行";
    }
};

#endif /* C0BF2BA5_C17A_4007_B403_C5CCB379961C */

main.cpp文章来源地址https://www.toymoban.com/news/detail-511010.html

#include "AbstractFactory.hpp"
#include "AbstractProduct.hpp"
#include "ConcreteFactory.hpp"
#include "ConcreteProduct.hpp"
#include "iostream"
using namespace std;
int main(int argc, char const *argv[])
{
    shared_ptr<Factory> factory;
    string conf = "china";

    if(conf == "china"){
        factory = make_shared<ChineseProduct>();
    }else if(conf == "japan"){
        factory = make_shared<JapaneseProduct>();
    }else{
        cout << " ERROR: Unknown" << endl;
    }
    shared_ptr<Movie> movie;
    shared_ptr<Book> book;
    movie = factory->productMovie();
    book = factory->productBook();
    std::cout << "获取一部电影: " << movie->showMoiewName() << std::endl;
    std::cout << "获取一本书: " << book->showBookName() << std::endl;

    return 0;
}

到了这里,关于抽象工厂模式(Abstract Factory)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++11 设计模式4. 抽象工厂(Abstract Factory)模式

    从前面我们已经使用了工厂方法模式 解决了一些问题。 现在 策划又提出了新的需求:对于各个怪物,在不同的场景下,怪物的面板数值会发生变化,     //怪物分类:亡灵类,元素类,机械类     //战斗场景分类:沼泽地区,山脉地区,城镇。 那么就有9类怪物====沼泽地

    2024年04月14日
    浏览(45)
  • 设计模式-抽象工厂模式(Abstract Factory Pattern)结构|原理|优缺点|场景|示例

     目录         设计模式(分类)        设计模式(六大原则)        创建型         工厂方法         抽象工厂模式        单例模式        建造者模式        原型模式      结构型         适配器模式        装饰器模式      

    2024年04月22日
    浏览(38)
  • 《golang设计模式》第一部分·创建型模式-04-抽象工厂模式(Abstract Factory)

    在不具体指定产品类的情况下,为相互关联的产品簇或产品集提供创建接口,并向客户隐藏具体产品创建的细节或表示的对象。 AbstractFactory(抽象工厂):它声明了一组用于创建产品的方法,每一个方法对应一种产品。 ConcreteFactory(具体工厂):它实现了在抽象工厂中声明

    2024年02月14日
    浏览(44)
  • Abstract Factory Pattern 抽象工厂模式简介与 C# 示例【创建型】【设计模式来了】

    一句话解释:   提供一个接口,以创建一系列相关或相互依赖的抽象对象,而无需指定它们具体的类。 (将一系列抽象类装进接口,一次接口实现,就必须实例化这一系列抽象类) 抽象工厂模式(Abstract Factory Pattern)是一种创建型模式。它用于创建一组相关对象的家族。

    2024年02月07日
    浏览(42)
  • Abstract Factory 抽象工厂

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。 其中: AbstractFactory声明一个创建抽象产品对象的操作接口。 ConcreteFactory实现创建具体产品对象的操作。 AbstractProduct为一类产品对象声明一个接口。 ConcreteProduct定义一个将被相应的具体工厂创建的

    2024年04月11日
    浏览(41)
  • 【Java基础教程】(十五)面向对象篇 · 第九讲:抽象类和接口——定义、限制与应用的细节,初窥模板设计模式、工厂设计模式与代理设计模式~

    掌握 抽象类和接口的定义、使用、区别、常见设计模式; 抽象类是代码开发中的重要组成部分,利用抽象类可以明确地定义子类需要覆写的方法,这样相当于在语法程度上对子类进行了严格的定义限制,代码的开发也就更加标准。下面具体介绍抽象类的概念。 普通类可以直

    2024年02月16日
    浏览(46)
  • 设计模式-工厂模式Factory

    一般情况下,工厂模式分为三种更加细分的类型:简单工厂、工厂方法和抽象工厂。 简单工厂叫作静态工厂方法模式(Static Factory Method Pattern) 现在有一个场景,需要一个资源加载器,要 根据不用的url 进行资源加载,但是如果我们将 所有的加载实现代码全部封装在了一个

    2024年02月09日
    浏览(40)
  • 【设计模式-04】Factory工厂模式

    简单工厂 静态工厂 工厂方法 FactoryMethod 产品维度扩展 抽象工厂 产品一族进行扩展 Spring IOC 任何可以产生对象的方法或类,都可以称之为工厂 单例也是一种工厂 不可咬文嚼字,死扣概念 为什么有了new之后,还要有工厂? 灵活控制生产过程 权限、日志、修饰... 任意定制交通

    2024年02月02日
    浏览(40)
  • 设计模式--工厂模式(Factory Pattern)

    工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,但是将对象的实例化过程推迟到子类中。工厂模式允许通过调用一个共同的接口方法来创建不同类型的对象,而无需暴露对象的实例化逻辑。 工厂模式的主要目标是解耦对象的创建和使用,以及

    2024年02月10日
    浏览(37)
  • 工厂方法模式(Factory Method)

    虚拟构造函数(Virtual Constructor)。 工厂方法 是一种创建型设计模式, 其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。 1. 问题 假设你正在开发一款物流管理应用。最初版本只能处理卡车运输,因此大部分代码都在位于名为“卡车”的类中。 一段时间

    2024年02月10日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包