【再谈设计模式】抽象工厂模式~对象创建的统筹者

一、引言

        在软件开发的世界里,高效、灵活且易于维护的代码结构是每个开发者追求的目标。设计模式就像是建筑蓝图中的经典方案,为我们提供了应对各种常见问题的有效策略。其中,抽象工厂模式在对象创建方面扮演着重要的角色,它如同一个统筹者,精心组织着一系列相关对象的创建过程,确保整个系统的高效运转和易于扩展。无论是构建大型企业级应用还是小型工具软件,理解和运用抽象工厂模式都能让我们的代码更加优雅、健壮。

二、定义与描述

        抽象工厂设计模式是一种创建对象的设计模式,它提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。简单来说,抽象工厂模式就像是一个工厂的抽象层,这个抽象层定义了创建多种不同类型产品的方法,但不涉及具体产品的创建细节。

三、抽象背景

        在软件开发中,当系统需要创建一系列相关的对象时,例如一个游戏可能需要创建不同类型的角色(战士、法师等)以及与这些角色相关的武器、装备等对象。如果直接在代码中实例化这些对象,将会导致代码的高度耦合,即对象的创建逻辑与使用逻辑紧密地交织在一起。当需要添加新的角色类型或者修改对象的创建逻辑时,就需要在大量的代码中进行修改,这不仅容易出错,而且维护成本极高。抽象工厂模式的出现就是为了解决这种对象创建的复杂性和耦合性问题。

四、适用场景与现实问题解决

(一)适用场景

  • 多平台应用开发
    • 当开发一个跨平台的应用时,例如同时支持Windows、Linux和Mac操作系统的图形界面应用。不同平台下的窗口、按钮、菜单等界面组件虽然功能相似,但实现方式不同。抽象工厂模式可以用于创建与特定平台相关的界面组件系列,使得代码能够轻松地在不同平台间切换,而不需要在每个使用界面组件的地方都进行大量的条件判断。

  • 游戏开发
    • 在游戏中,不同的游戏场景可能需要不同类型的游戏元素。例如,一个冒险游戏可能有森林场景、沙漠场景等,每个场景中都有独特的怪物、道具和地形。抽象工厂模式可以用来创建这些与特定场景相关的游戏元素系列,保证游戏元素之间的兼容性和一致性。

(二)现实问题解决

  • 假设我们正在开发一个汽车制造系统。汽车由多个部件组成,如发动机、轮胎、座椅等,并且有不同类型的汽车,如轿车、SUV等。使用抽象工厂模式,我们可以创建抽象的汽车部件工厂,它定义了创建发动机、轮胎和座椅等部件的抽象方法。然后针对轿车和SUV分别创建具体的工厂实现类,这些具体工厂类负责创建各自类型汽车所需的特定部件。这样,当需要添加一种新类型的汽车时,只需要创建一个新的具体工厂类,而不需要修改使用这些部件的汽车组装代码,从而降低了系统的耦合度,提高了可维护性和可扩展性。

五、现实生活的例子

        以家具制造为例。家具厂可以看作是一个抽象工厂,它有生产不同风格家具(如现代风格、古典风格)的能力。对于现代风格家具,工厂可以生产现代风格的沙发、餐桌和椅子;对于古典风格家具,工厂可以生产古典风格的沙发、餐桌和椅子。这里,家具厂就是抽象工厂,它定义了生产沙发、餐桌和椅子的抽象方法,而现代风格家具厂和古典风格家具厂就是具体的工厂实现类,它们按照各自的风格生产具体的家具产品。

六、初衷与问题解决

  • 初衷:抽象工厂模式的初衷是为了将对象的创建和使用分离,提高代码的灵活性和可维护性。通过提供一个抽象的创建对象的接口,使得代码的依赖关系更加抽象化,减少对具体类的依赖。
  • 问题解决:它解决了对象创建逻辑与使用逻辑耦合的问题。在大型软件系统中,如果没有这种模式,每当需要创建新类型的对象或者修改对象的创建逻辑时,可能需要在多个地方修改代码。而抽象工厂模式通过将对象创建逻辑封装在具体的工厂类中,只需要修改或扩展工厂类,而不需要影响使用这些对象的其他代码部分。

七、代码示例

(一)Java示例

// 抽象产品:座椅
interface Seat {
    void sitOn();
}

// 抽象产品:轮胎
interface Tire {
    void roll();
}

// 抽象产品:发动机
interface Engine {
    void start();
}

// 抽象工厂
interface CarFactory {
    Seat createSeat();
    Tire createTire();
    Engine createEngine();
}

// 具体产品:轿车座椅
class SedanSeat implements Seat {
    @Override
    public void sitOn() {
        System.out.println("坐在轿车座椅上。");
    }
}

// 具体产品:轿车轮胎
class SedanTire implements Tire {
    @Override
    public void roll() {
        System.out.println("轿车轮胎滚动。");
    }
}

// 具体产品:轿车发动机
class SedanEngine implements Engine {
    @Override
    public void start() {
        System.out.println("轿车发动机启动。");
    }
}

// 具体工厂:轿车工厂
class SedanFactory implements CarFactory {
    @Override
    public Seat createSeat() {
        return new SedanSeat();
    }

    @Override
    public Tire createTire() {
        return new SedanTire();
    }

    @Override
    public Engine createEngine() {
        return new SedanEngine();
    }
}


public class Main {
    public static void main(String[] args) {
        CarFactory sedanFactory = new SedanFactory();
        Seat sedanSeat = sedanFactory.createSeat();
        Tire sedanTire = sedanFactory.createTire();
        Engine sedanEngine = sedanFactory.createEngine();

        sedanSeat.sitOn();
        sedanTire.roll();
        sedanEngine.start();
    }
}

(二)C++示例

#include <iostream>

// 抽象产品:座椅
class Seat {
public:
    virtual void sitOn() = 0;
};

// 抽象产品:轮胎
class Tire {
public:
    virtual void roll() = 0;
};

// 抽象产品:发动机
class Engine {
public:
    virtual void start() = 0;
};

// 抽象工厂
class CarFactory {
public:
    virtual Seat* createSeat() = 0;
    virtual Tire* createTire() = 0;
    virtual Engine* createEngine() = 0;
};

// 具体产品:轿车座椅
class SedanSeat : public Seat {
public:
    void sitOn() override {
        std.out << "坐在轿车座椅上。" << std::endl;
    }
};

// 具体产品:轿车轮胎
class SedanTire : public Tire {
public:
    void roll() override {
        std::cout << "轿车轮胎滚动。" << std::endl;
    }
};

// 具体产品:轿车发动机
class SedanEngine : public Engine {
public:
    void start() override {
        std::cout << "轿车发动机启动。" << std::endl;
    }
};

// 具体工厂:轿车工厂
class SedanFactory : public CarFactory {
public:
    Seat* createSeat() override {
        return new SedanSeat();
    }
    Tire* createTire() override {
        return new SedanTire();
    }
    Engine* createEngine() override {
        return new SedanEngine();
    }
};


int main() {
    CarFactory* sedanFactory = new SedanFactory();
    Seat* sedanSeat = sedanFactory->createSeat();
    Tire* sedanTire = sedanFactory->createTire();
    Engine* sedanEngine = sedanFactory->createEngine();

    sedanSeat->sitOn();
    sedanTire->roll();
    sedanEngine->start();

    delete sedanSeat;
    delete sedanTire;
    delete sedanEngine;
    delete sedanFactory;

    return 0;
}

(三)Python示例

# 抽象产品:座椅
class Seat:
    def sitOn(self):
        pass


# 抽象产品:轮胎
class Tire:
    def roll(self):
        pass


# 抽象产品:发动机
class Engine:
    def start(self):
        pass


# 抽象工厂
class CarFactory:
    def createSeat(self):
        pass
    def createTire(self):
        pass
    def createEngine(self):
        pass


# 具体产品:轿车座椅
class SedanSeat(Seat):
    def sitOn(self):
        print("坐在轿车座椅上。")


# 具体产品:轿车轮胎
class SedanTire(Tire):
    def roll(self):
        print("轿车轮胎滚动。")


# 具体产品:轿车发动机
class SedanEngine(Engine):
    def start(self):
        print("轿车发动机启动。")


# 具体工厂:轿车工厂
class SedanFactory(CarFactory):
    def createSeat(self):
        return SedanSeat()
    def createTire(self):
        return SedanTire()
    def createEngine(self):
        return SedanEngine()


if __name__ == "__main__":
    sedanFactory = SedanFactory()
    sedanSeat = sedanFactory.createSeat()
    sedanTire = sedanFactory.createTire()
    sedanEngine = sedanFactory.createEngine()

    sedanSeat.sitOn();
    sedanTire.roll();
    sedanEngine.start();

(四)Go示例

// 抽象产品:座椅
type Seat interface {
    SitOn()
}

// 抽象产品:轮胎
type Tire interface {
    Roll()
}

// 抽象产品:发动机
type Engine interface {
    Start()
}

// 抽象工厂
type CarFactory interface {
    CreateSeat() Seat
    CreateTire() Tire
    CreateEngine() Engine
}

// 具体产品:轿车座椅
type SedanSeat struct{}

func (s SedanSeat) SitOn() {
    println("坐在轿车座椅上。")
}

// 具体产品:轿车轮胎
type SedanTire struct{}

func (s SedanTire) Roll() {
    println("轿车轮胎滚动。")
}

// 具体产品:轿车发动机
type SedanEngine struct{}

func (s SedanEngine) Start() {
    println("轿车发动机启动。")
}

// 具体工厂:轿车工厂
type SedanFactory struct{}

func (s SedanFactory) CreateSeat() Seat {
    return SedanSeat{}
}
func (s SedanFactory) CreateTire() Tire {
    return SedanTire{}
}
func (s SedanFactory) CreateEngine() Engine {
    return SedanEngine{}
}


func main() {
    sedanFactory := SedanFactory{}
    sedanSeat := sedanFactory.CreateSeat()
    sedanTire := sedanFactory.CreateTire()
    sedanEngine := sedanFactory.CreateEngine()

    sedanSeat.SitOn()
    sedanTire.Roll()
    sedanEngine.Start()
}

八、抽象工厂设计模式的优缺点

(一)优点

  • 解耦对象的创建和使用
    • 使用者不需要知道对象的具体创建过程,只需要关心如何使用对象。这使得代码的职责更加清晰,有利于团队开发和代码维护。
  • 提高代码的可维护性和可扩展性
    • 当需要添加新的产品类型或者修改产品的创建逻辑时,只需要在具体的工厂类中进行操作,不需要修改使用这些对象的其他代码部分。
  • 便于代码的复用
    • 抽象工厂可以被多个地方复用,只要这些地方需要创建相同系列的产品。同时,具体的产品类也可以在其他场景下复用。

(二)缺点

  • 增加代码复杂度
    • 引入抽象工厂模式需要创建更多的类和接口,对于简单的应用场景,可能会使代码变得过于复杂。
  • 不易于理解
    • 对于初学者或者不熟悉设计模式的开发人员来说,抽象工厂模式的概念和实现方式可能比较难以理解,需要一定的学习成本。

九、抽象工厂设计模式的升级版

  • 抽象工厂模式的一个升级版是工厂方法模式的组合使用。在大型系统中,可能会存在多个抽象工厂,每个抽象工厂又可以有多个具体的工厂方法。这种组合模式可以进一步细化对象的创建逻辑,提高代码的灵活性。例如,在汽车制造系统中,可以先有一个抽象的汽车部件总装工厂(抽象工厂),然后这个总装工厂中的每个部件创建可以采用工厂方法模式,即发动机的创建有专门的发动机工厂方法,轮胎的创建有专门的轮胎工厂方法等。这样可以更加细致地管理和扩展对象的创建逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/914940.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】ELF可执行程序和动态库加载

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;Linux系统编程 这里将会不定期更新有关Linux的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 文章目…

SpringBootCloud 服务注册中心Nacos对服务进行管理

介绍 Nacos&#xff08;Naming and Configuration Service&#xff09;是一个开源的、动态的服务发现、配置管理和服务管理平台&#xff0c;特别适用于云原生应用和微服务架构。它可以作为服务注册中心&#xff0c;用于微服务的注册、发现、配置管理等。在微服务架构中&#x…

八款局域网监控软件优选|2024最新排行榜(企业老板收藏篇)

在当今数字化办公的时代&#xff0c;企业和组织对于局域网电脑监控的需求日益增长。无论是为了保障信息安全、提高员工工作效率&#xff0c;还是为了规范网络行为&#xff0c;一款优秀的局域网电脑监控软件都能发挥重要作用。市面上的监控软件种类繁多&#xff0c;功能各异&…

限价订单簿中的高频交易

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学&#xff0c;点击下方链接报名&#xff1a; 量化投资速成营&#xff08;入门课程&#xff09; Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…

丹摩征文活动|CogVideoX-2b:从0到1,轻松完成安装与部署!

丹摩征文活动 | CogVideoX-2b&#xff1a;从0到1&#xff0c;轻松完成安装与部署&#xff01; CogVideoX 介绍 CogVideoX的问世&#xff0c;标志着视频制作技术迈入了一个全新的时代。它不仅打破了传统视频制作在效率与质量之间的平衡难题&#xff0c;还通过其先进的3D变分自…

Creo 9.0 中文版软件下载安装教程

[软件名称]&#xff1a;Creo 9.0 [软件语言]&#xff1a;简体中文 [软件大小]&#xff1a;5.2G [安装环境]&#xff1a;Win11/Win10/ [硬件要求]&#xff1a;内存8G及以上 下载方法&#xff1a;电脑打开浏览器&#xff0c;复制下载链接&#xff0c;粘贴至浏览器网址栏&…

RT-DETR融合CVPR[2024]无膨胀多尺度卷积PKI模块及相关改进思路

RT-DETR使用教程&#xff1a; RT-DETR使用教程 RT-DETR改进汇总贴&#xff1a;RT-DETR更新汇总贴 《Poly Kernel Inception Network for Remote Sensing Detection》 一、 模块介绍 论文链接&#xff1a;https://arxiv.org/abs/2403.06258 代码链接&#xff1a;https://github…

ubuntu-desktop-24.04上手指南(更新阿里源、安装ssh、安装chrome、设置固定IP、安装搜狗输入法)

ubuntu-desktop-24.04上手指南(更新阿里源、安装ssh、安装chrome、设置固定IP、安装搜狗输入法) 一、更新并安装基础软件 #切换root用户 sudo su -#更新 apt update #升级 apt upgrade#install vim apt install vim#install net-tools apt install net-tools二、安装ssh并设置…

[CKS] K8S ServiceAccount Set Up

最近准备花一周的时间准备CKS考试&#xff0c;在准备考试中发现有一个题目关于Rolebinding的题目。 ​ 专栏其他文章: [CKS] Create/Read/Mount a Secret in K8S-CSDN博客[CKS] Audit Log Policy-CSDN博客 -[CKS] 利用falco进行容器日志捕捉和安全监控-CSDN博客[CKS] K8S Netwo…

介绍和安装及数据类型

1、介绍和安装 1.1、简介 ClickHouse是俄罗斯的Yandex于2016年开源的列式存储数据库&#xff08;DBMS&#xff09;&#xff0c;使用C语言编写&#xff0c;主要用于在线分析处理查询&#xff08;OLAP&#xff09;&#xff0c;能够使用SQL查询实时生成分析数据报告。 OLAP&…

算法魅力-二分查找实战

目录 前言 算法定义 朴素二分模版 二分查找 二分的边界查找 在排序数组中查找元素的第一个和最后一个位置&#xff08;medium&#xff09; 暴力算法 二分查找 边界查找分析 山峰数组的峰顶 暴力枚举 二分查找 搜索旋转排序数组中的最小值&#xff08;medium&#xf…

Linux第四讲:Git gdb

Linux第四讲&#xff1a;Git && gdb 1.版本控制器Git1.1理解版本控制1.2理解协作开发1.3Git的历史1.4Git的操作1.4.1仓库创建解释、仓库克隆操作1.4.2本地文件操作三板斧1.4.3文件推送详细问题 2.调试器 -- gdb/cgdb使用2.1调试的本质是什么2.2watch命令2.3set var命令…

海底捞点单

单点锅底推荐&#xff1a; 番茄锅底通31 牛油麻辣通44 清汤麻辣备44 菌汤锅底通31 小吃&主食&#xff1a; 捞派捞面一黄金小馒头一茴香小油条 红糖枇杷一小酥肉 DIY锅底推荐&#xff1a; 1.寿喜锅&#xff1a;海鲜味酱4勺陈醋1勺蚝油2勺盐适量白糖7勺 芹菜1勺 2.麻辣锅底…

PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸

小编最近有一篇png图片要批量压缩&#xff0c;大小都在5MB之上&#xff0c;在网上找了半天要么就是有广告&#xff0c;要么就是有毒&#xff0c;要么就是功能复杂&#xff0c;整的我心烦意乱。 于是我自己用python写了一个纯净工具&#xff0c;只能压缩png图片&#xff0c;没任…

达梦8数据库适配ORACLE的8个参数

目录 1、概述 1.1 概述 1.2 实验环境 2、参数简介 3、实验部分 3.1 参数BLANK_PAD_MODE 3.2 参数COMPATIBLE_MODE 3.3 参数ORDER_BY_NULLS_FLAG 3.4 参数DATETIME_FMT_MODE 3.5 参数PL_SQLCODE_COMPATIBLE 3.6 参数CALC_AS_DECIMAL 3.7 参数ENABLE_PL_SYNONYM 3.8…

如何低成本、零代码开发、5分钟内打造一个企业AI智能客服?

传统客服因员工效率低、时段需求波动大、数据管理费时费力等管理难题&#xff0c;导致难以满足用户需求&#xff0c;无法深入挖掘客服数据价值&#xff0c;造成客源流失。而智能体搭建的“智能客服”能借助大模型和知识库知识&#xff0c;助力实现数字化运营&#xff0c;破解企…

CC1链学习记录

&#x1f338; 前言 上篇文章学习记录了URLDNS链&#xff0c;接下来学习一下Common-Colections利用链。 &#x1f338; 相关介绍 Common-Colections是Apache软件基金会的项目&#xff0c;对Java标准的Collections API提供了很好的补充&#xff0c;在其基础上对常用的数据结构…

【启明智显分享】5G CPE为什么适合应用在连锁店中?

连锁门店需要5G CPE来满足其日益增长的网络需求&#xff0c;提升整体运营效率和竞争力。那么为什么5G CPE适合连锁店应用呢&#xff0c;小编为此做了整理&#xff0c;主要是基于以下几个方面的原因&#xff1a; 一、高效稳定的网络连接 1、高速数据传输&#xff1a; 5G CPE能…

怎么禁止文件外发?企业如何禁止文件外发,教你6种方法,综合运用效果加倍

在当今数字化的商业环境中&#xff0c;企业内部文件承载着大量关键信息&#xff0c;犹如企业的命脉。这些文件可能包含着核心技术机密、客户资料、未公开的战略规划以及敏感的财务数据等&#xff0c;它们是企业在激烈市场竞争中立足的重要资产。然而&#xff0c;随着信息传播途…

FPGA学习笔记#8 Vitis HLS优化总结和案例程序的优化

本笔记使用的Vitis HLS版本为2022.2&#xff0c;在windows11下运行&#xff0c;仿真part为xcku15p_CIV-ffva1156-2LV-e&#xff0c;主要根据教程&#xff1a;跟Xilinx SAE 学HLS系列视频讲座-高亚军进行学习 学习笔记&#xff1a;《FPGA学习笔记》索引 FPGA学习笔记#1 HLS简介及…