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

embedded/2024/11/20 11:49:56/

一、引言

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

二、定义与描述

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

三、抽象背景

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

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

(一)适用场景

  • 多平台应用开发
    • 当开发一个跨平台的应用时,例如同时支持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 {@Overridepublic void sitOn() {System.out.println("坐在轿车座椅上。");}
}// 具体产品:轿车轮胎
class SedanTire implements Tire {@Overridepublic void roll() {System.out.println("轿车轮胎滚动。");}
}// 具体产品:轿车发动机
class SedanEngine implements Engine {@Overridepublic void start() {System.out.println("轿车发动机启动。");}
}// 具体工厂:轿车工厂
class SedanFactory implements CarFactory {@Overridepublic Seat createSeat() {return new SedanSeat();}@Overridepublic Tire createTire() {return new SedanTire();}@Overridepublic 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):passdef createTire(self):passdef 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() SeatCreateTire() TireCreateEngine() 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()
}

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

(一)优点

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

(二)缺点

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

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

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

http://www.ppmy.cn/embedded/139067.html

相关文章

【Linux】常用命令练习

一、常用命令 1、在/hadoop目录下创建src和WebRoot两个文件夹 分别创建&#xff1a;mkdir -p /hadoop/src mkdir -p /hadoop/WebRoot 同时创建&#xff1a;mkdir -p /hadoop/{src,WebRoot}2、进入到/hadoop目录&#xff0c;在该目录下创建.classpath和README文件 分别创建&am…

力扣第 56 题 合并区间

解法思路 区间排序&#xff1a; 按区间的起点升序排序。如果起点相同&#xff0c;则按终点升序排序。 遍历合并&#xff1a; 使用一个动态数组存储合并后的结果。遍历排序后的区间&#xff1a; 如果当前区间的起点在结果数组最后一个区间的终点后&#xff0c;直接加入结果数组…

ML 系列: 第 23 节 — 离散概率分布 (多项式分布)

目录 一、说明 二、多项式分布公式 2.1 多项式分布的解释 2.2 示例 2.3 特殊情况&#xff1a;二项分布 2.4 期望值 &#xff08;Mean&#xff09; 2.5 方差 三、总结 3.1 python示例 一、说明 伯努利分布对这样一种情况进行建模&#xff1a;随机变量可以采用两个可能的值&#…

【Java Web】Ajax 介绍及 jQuery 实现

文章目录 AJAX介绍XMLHttpRequestjQuery实现Ajax$.ajax()$().load()$.get()$.post() AJAX介绍 AJAX&#xff08;Asynchronous JavaScript and XML&#xff09;是一种创建高效、动态网页应用的网页开发技术。它允许在不重新加载整个页面的情况下进行异步数据更新和交互&#xf…

torch.utils.data.dataset 的数据组织形式——python list、dict、tuple内存消耗量

在Pytorch中&#xff0c;我们需要通过torch.utils.data.dataset来实现数据的读取。torch.utils.data.dataset是一种非流式的数据读取策略&#xff0c;需要将数据一次性导入至内存中.如果数据规模过大&#xff0c;可能存在内存不够的问题。 import torch from torch.utils.data…

Spark使用过程中的 15 个常见问题、详细解决方案

目录 问题 1&#xff1a;Spark 作业超时问题描述解决方案Python 实现 问题 2&#xff1a;内存溢出问题描述解决方案Python 实现 问题 3&#xff1a;Shuffle 性能问题问题描述解决方案Python 实现 问题 4&#xff1a;Spark 作业调度不均问题描述解决方案Python 实现 问题 5&…

美创科技膺选CNVD技术组支撑单位!

国家信息安全漏洞共享平台&#xff08;CNVD&#xff09;发布安全公告&#xff08;编号&#xff1a;CNTA-2024-0019&#xff09;&#xff0c;宣布新增八家支撑单位。美创科技凭借数据安全领域的技术实力和专业服务能力&#xff0c;顺利通过支撑能力候选考察&#xff0c;首次获得…

SQL 语句优化及编程方法

DBMS生成的执行计划在很大程度上要受到代码外部结构的影响。因此要想优化查询性能&#xff0c;就必须要知道如何写代码才能使优化器的执行效率更高。 但是&#xff0c;不能为了“效率”牺牲代码的可读性&#xff0c;要让代码清晰。 1 查询优化 在解决SQL造成的性能问题时&am…