关于简单工厂、工厂方法和抽象工厂模式的区别

news/2025/2/7 3:45:18/

简单工厂模式(Simple Factory Pattern)

简单工厂方法模式是一种创建型设计模式,它提供了一个统一的接口来创建对象,但隐藏了对象的具体实现细节。简单工厂模式通过一个工厂类,根据不同的参数来创建不同的产品对象,使得客户端代码与具体产品的创建过程解耦。
简单工厂模式包含以下几个核心组件:

  1. 工厂类(Factory):负责创建产品对象的类。它通常包含一个静态方法,根据传入的参数来创建不同的产品对象。
  2. 抽象产品类(Product):定义产品的共同接口,所有具体产品类都必须实现这个接口。
  3. 具体产品类(Concrete Product):实现抽象产品类接口的具体产品。工厂类根据不同的参数来创建不同的具体产品对象。

优点

简单工厂模式的优点包括:

  1. 客户端与具体产品解耦:客户端只需要与工厂类进行交互,不需要直接依赖具体产品类,降低了客户端的复杂性。
  2. 隐藏对象创建细节:客户端不需要关心具体产品的创建过程,只需要关心如何使用产品。
  3. 简化对象创建:通过工厂类集中管理对象的创建,可以提供统一的创建方式和参数验证,简化了对象的创建过程。

缺点

  1. 不符合开闭原则:当需要新增加一种产品时,需要修改工厂类的代码,违反了开闭原则。
  2. 工厂类职责过重:随着产品种类的增多,工厂类的职责会变得越来越重,可能会导致工厂类的代码臃肿。
  3. 不易扩展:由于工厂类集中了所有产品的创建逻辑,当需要添加新的产品时,需要修改工厂类的代码,扩展性较差。

例子

以下是一个使用简单工厂模式创建不同类型动物的示例:```javascript
// 抽象产品类 - 动物
class Animal {constructor(name) {this.name = name;}sound() {// 抽象方法,具体的动物类需要实现该方法}
}// 具体产品类 - 狗
class Dog extends Animal {sound() {return "汪汪汪!";}
}// 具体产品类 - 猫
class Cat extends Animal {sound() {return "喵喵喵!";}
}// 简单工厂类
class AnimalFactory {createAnimal(type, name) {switch (type) {case "dog":return new Dog(name);case "cat":return new Cat(name);default:throw new Error("Invalid animal type.");}}
}// 使用简单工厂创建对象
const factory = new AnimalFactory();
const dog = factory.createAnimal("dog", "旺财");
const cat = factory.createAnimal("cat", "小花");console.log(dog.sound()); // 输出:汪汪汪!
console.log(cat.sound()); // 输出:喵喵喵!

在上述示例中,我们定义了一个抽象产品类 Animal,它有一个抽象方法 sound()。然后,我们创建了两个具体产品类 DogCat,它们分别继承自 Animal 并实现了 sound() 方法。

接下来,我们定义了一个简单工厂类 AnimalFactory,它有一个 createAnimal() 方法,根据传入的类型参数来创建不同的动物对象。

最后,我们使用简单工厂类创建了一个 AnimalFactory 实例,并使用 createAnimal() 方法创建了一个狗对象和一个猫对象。通过调用对象的 sound() 方法,我们可以分别输出它们的声音。

这个例子展示了如何使用简单工厂模式在JavaScript中创建不同类型的对象,通过工厂类将对象的创建过程与客户端代码解耦。

总结

简单工厂模式适用于以下情况:

  1. 需要创建的对象较少:当需要创建的对象种类较少且相对稳定时,可以使用简单工厂模式。
  2. 客户端不关心对象的具体实现:客户端只需要使用对象的共同接口,对于具体实现不关心时,可以使用简单工厂模式。总之,简单工厂模式是一种简单实用的创建型设计模式,适用于创建对象较少且相对稳定的情况。但需要注意,它可能违反开闭原则,并且随着产品种类的增多,工厂类的职责会变得过重。在设计时,应根据具体需求和情况来选择合适的设计模式。

工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它通过定义一个创建对象的接口,但将具体对象的创建延迟到子类中实现。工厂方法模式使得一个类的实例化延迟到其子类,从而实现了对象的创建与使用的解耦。

工厂方法模式

工厂方法模式包含以下几个核心组件:

  1. 抽象产品类(Product):定义产品的共同接口,所有具体产品类都必须实现这个接口。

  2. 具体产品类(Concrete Product):实现抽象产品类接口的具体产品。

  3. 抽象工厂类(Factory):定义创建产品的抽象方法,由子类来实现具体的产品创建。

  4. 具体工厂类(Concrete Factory):实现抽象工厂类的抽象方法,负责创建具体的产品对象。

工厂方法模式的工作流程如下:

  1. 客户端通过调用具体工厂类的方法来创建产品对象。

  2. 具体工厂类根据需要创建相应的具体产品对象,并返回给客户端。

  3. 客户端通过产品的共同接口来使用具体产品对象,而不需要关心具体产品的创建过程。

工厂方法模式与简单工厂模式的区别在于,工厂方法模式将对象的创建延迟到子类中实现,每个具体产品都有对应的具体工厂类,而简单工厂模式通过一个工厂类来创建所有的产品对象。

优点

  1. 符合开闭原则:当需要新增加一种产品时,只需要创建相应的具体产品类和具体工厂类,而不需要修改已有的代码。

  2. 客户端与具体产品解耦:客户端只需要与抽象工厂和抽象产品进行交互,不需要直接依赖具体产品类,降低了客户端的复杂性。

  3. 支持多态性:每个具体工厂类都可以返回不同类型的具体产品,通过多态性来实现不同产品的创建和使用。

缺点

  1. 类的个数增加:每个具体产品都需要对应一个具体工厂类,导致类的个数增加。

  2. 增加系统的抽象性和理解难度:工厂方法模式引入了抽象工厂和抽象产品的概念,增加了系统的抽象性和理解难度。

例子

// 抽象产品类 - 按钮
class Button {render() {// 抽象方法,具体的按钮类需要实现该方法}
}// 具体产品类 - 圆形按钮
class CircleButton extends Button {render() {console.log("渲染圆形按钮");}
}// 具体产品类 - 方形按钮
class SquareButton extends Button {render() {console.log("渲染方形按钮");}
}// 抽象工厂类 - 按钮工厂
class ButtonFactory {createButton() {// 抽象方法,由具体的工厂类来实现该方法}
}// 具体工厂类 - 圆形按钮工厂
class CircleButtonFactory extends ButtonFactory {createButton() {return new CircleButton();}
}// 具体工厂类 - 方形按钮工厂
class SquareButtonFactory extends ButtonFactory {createButton() {return new SquareButton();}
}// 使用工厂方法创建对象
function createButton(factory) {const button = factory.createButton();button.render();
}// 创建圆形按钮工厂
const circleButtonFactory = new CircleButtonFactory();
createButton(circleButtonFactory); // 输出:渲染圆形按钮// 创建方形按钮工厂
const squareButtonFactory = new SquareButtonFactory();
createButton(squareButtonFactory); // 输出:渲染方形按钮

总结

工厂方法模式适用于以下情况:

  1. 需要创建的对象种类较多:当需要创建的对象种类较多且相对稳定时,可以使用工厂方法模式。

  2. 客户端不关心对象的具体实现:客户端只需要使用对象的共同接口,对于具体实现不关心时,可以使用工厂方法模式。

抽象工厂模式

抽象工厂模式是一种创建型设计模式,用于创建一系列相关或相互依赖的对象。它提供了一种方式来封装对象的创建过程,使得客户端代码与具体的产品类解耦。

在抽象工厂模式中,有以下几个核心角色:

  1. 抽象工厂(Abstract Factory):定义了创建一系列相关产品对象的接口。它声明了一组用于创建不同产品对象的抽象方法。

  2. 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建一系列具体的产品对象。每个具体工厂类对应一族产品。

  3. 抽象产品(Abstract Product):定义了一类产品对象的接口。它可以是一个具体产品类的抽象,也可以是一个接口。

  4. 具体产品(Concrete Product):实现了抽象产品接口,具体工厂类创建的产品就是具体产品的实例。

使用抽象工厂模式的主要步骤如下:

  1. 定义抽象产品接口:创建一系列产品对象所共有的接口,并声明产品对象的方法。

  2. 定义抽象工厂接口:声明用于创建产品对象的抽象方法。

  3. 实现具体产品类:实现抽象产品接口,定义具体产品的具体行为。

  4. 实现具体工厂类:实现抽象工厂接口,实现抽象方法来创建具体产品对象。

  5. 在客户端代码中使用抽象工厂:客户端通过抽象工厂接口来创建产品对象,而不直接依赖具体产品类。这样可以使客户端与具体产品类解耦,增加了灵活性和可扩展性。

优点

  • 提供了一种封装对象创建过程的方式,使得客户端代码与具体产品类解耦,增加了灵活性和可扩展性。

  • 支持产品族的扩展,即可以创建一系列相关的产品对象。

  • 符合开闭原则,当需要增加新的产品族时,只需要添加相应的具体工厂类和具体产品类,而无需修改已有代码。

缺点

  • 增加新的产品等级结构(即新的抽象产品类)比较困难,需要修改抽象工厂接口和所有的具体工厂类。

  • 当产品族中的产品等级结构发生变化时,需要修改抽象工厂接口和所有的具体工厂类。

例子

// 抽象产品类 - 按钮
class Button {render() {// 抽象方法,具体的按钮类需要实现该方法}
}// 具体产品类 - 圆形按钮
class CircleButton extends Button {render() {console.log("渲染圆形按钮");}
}// 具体产品类 - 方形按钮
class SquareButton extends Button {render() {console.log("渲染方形按钮");}
}// 抽象产品类 - 文本框
class TextBox {render() {// 抽象方法,具体的文本框类需要实现该方法}
}// 具体产品类 - 圆形文本框
class CircleTextBox extends TextBox {render() {console.log("渲染圆形文本框");}
}// 具体产品类 - 方形文本框
class SquareTextBox extends TextBox {render() {console.log("渲染方形文本框");}
}// 抽象工厂类 - UI工厂
class UIFactory {createButton() {// 抽象方法,由具体的工厂类来实现该方法}createTextBox() {// 抽象方法,由具体的工厂类来实现该方法}
}// 具体工厂类 - 圆形UI工厂
class CircleUIFactory extends UIFactory {createButton() {return new CircleButton();}createTextBox() {return new CircleTextBox();}
}// 具体工厂类 - 方形UI工厂
class SquareUIFactory extends UIFactory {createButton() {return new SquareButton();}createTextBox() {return new SquareTextBox();}
}// 使用抽象工厂创建对象
function createUI(factory) {const button = factory.createButton();const textBox = factory.createTextBox();button.render();textBox.render();
}// 创建圆形UI工厂
const circleUIFactory = new CircleUIFactory();
createUI(circleUIFactory);
// 输出:
// 渲染圆形按钮
// 渲染圆形文本框// 创建方形UI工厂
const squareUIFactory = new SquareUIFactory();
createUI(squareUIFactory);
// 输出:
// 渲染方形按钮
// 渲染方形文本框

总结

抽象工厂模式适用于需要创建一系列相关产品对象,并且需要增加新的产品族时。它提供了一种灵活的方式来封装对象的创建过程,使得客户端代码与具体产品类解耦。

三者对比

  • 简单工厂模式适用于对象的创建逻辑相对简单的情况,但不符合开闭原则。
  • 工厂方法模式适用于需要创建单个产品对象的情况,每个产品有对应的具体工厂类。
  • 抽象工厂模式适用于需要创建一系列相关产品对象的情况,支持产品族的扩展,但增加了系统的抽象性和理解难度。

选择适合的模式取决于具体的需求和设计考虑。如果只有少量的产品需要创建,并且创建逻辑简单,可以使用简单工厂模式;如果有多个产品需要创建,并且每个产品都有对应的工厂类,可以使用工厂方法模式;如果需要创建一系列相关产品对象,并且支持产品族的扩展,可以使用抽象工厂模式。


http://www.ppmy.cn/news/1198350.html

相关文章

Spring Security OAuth 2.0 资源服务器— JWT

目录 一、JWT的最小依赖 二、JWT的最基本配置 1、指定授权服务器 2、初始预期(Startup Expectations) 3、运行时预期(Runtime Expectations) 三、JWT认证是如何工作的 四、直接指定授权服务器 JWK Set Uri 五、提供 audie…

【Python基础】Python编程入门自学笔记,基础大全,一篇到底!

📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…

Android Studio(控件常用属性)

通用属性 属性描述android:id用于为视图指定唯一的标识符。android:layout_width用于指定视图的宽度。android:layout_height用于指定视图的高度。android:layout_margin用于指定视图周围的空白区域。android:layout_padding用于指定视图内部的填充区域。android:background用…

C++11范围for

在C98中,不同的STL容器和C风格数组的遍历方式各不相同,写法也不统一,而且不够简洁。而C11基于范围的for循环可以简洁并且统一的方式遍历STL容器和C风格数组。 在介绍for循环新的语法之前,简单来看一下for循环之前遍历STL容器的例…

JavaScript 自定义对象

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>JS-定义对象</title> </head><body&g…

类锁和实例对象锁你分清了吗?

系列文章目录 文章目录 系列文章目录前言一、什么是锁竞争&#xff1f;二、什么是类锁&#xff1f;什么是实例对象锁&#xff1f;三、给类对象加锁不是锁住了整个类四、总结 前言 java选手们应该都对锁不陌生&#xff0c;加锁了就是为保证操作语句的原子性&#xff0c;如果你是…

在本地安装LLAMA 2

方法一&#xff1a; Meta已将llama2开源&#xff0c;任何人都可以通过在meta ai上申请并接受许可证、提供电子邮件地址来获取模型。 Meta 将在电子邮件中发送下载链接。 下载llama2 获取download.sh文件&#xff0c;将其存储在mac上打开mac终端&#xff0c;执行 chmod x ./do…

lv9 嵌入式开发 数据库sqlite

1 数据库基本概念 数据&#xff08;Data&#xff09; 能够输入计算机并能被计算机程序识别和处理的信息集合 数据库 &#xff08;Database&#xff09; 数据库是在数据库管理系统管理和控制之下&#xff0c;存放在存储介质上的数据集合 2 常用的数据库 大型数据库…