目录
- 前言
- 一、设计模式简介
- 1. 什么是设计模式
- 2. 设计模式分类
- 3. 设计模式的优点
- 4. 设计模式的实践
- 二、单例模式
- 1. 单例模式的关键点
- 2. 单例模式的实现方式
- 饿汉式单例(Eager Initialization)
- 懒汉式单例(Lazy Initialization)
- 双重检查锁定(Double-Checked Locking)
- 登记式单例(Registry-based Singleton)
- 枚举式单例(Enum-based Singleton)
- 3. 单例模式的优缺点
- 4. 示例程序
- 三、工厂模式
- 1. 简单工厂模式
- 特点:
- 示例代码:
- 缺点:
- 2. 工厂方法模式
- 特点:
- 示例代码:
- 3. 抽象工厂模式
- 特点:
- 示例代码1:
- 示例代码2:
- 4. 使用场景
- 5. 总结
前言
关于并发编程的更多内容我会在后续的实际开发中进行总结,然后分享给大家!接下来将会和大家一起学习C++的设计模式
😷
一、设计模式简介
1. 什么是设计模式
(1)设计模式 是 软件开发人员在软件开发过程中 面临的 一般问题的解决方案。
(2)这些解决方案是众多软件开发人员经过 相当长的一段时间的 试验 和 错误总结出来的。
(3)使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。
2. 设计模式分类
设计模式提供了一种标准化的方法来处理软件设计中的问题,使得代码更加灵活、可维护和可重用。它们通常是在特定的上下文中应用,并在软件开发的不同阶段(如设计、编码、测试等)起到指导作用。
设计模式有23种左右。设计模式一般分为以下几类:
-
创建型模式(Creational Patterns):这些模式关注对象的创建过程,旨在将对象的创建与使用分离。常见的创建型模式包括(常用的是前三种):
- 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供全局访问点。
- 工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,但由子类决定要实例化的类。
- 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或互相依赖对象的接口,而无需指定具体类。
- 建造者模式(Builder Pattern):通过将一个复杂对象的构建过程与它的表示分离,来构建一个复杂对象。
- 原型模式(Prototype Pattern):通过复制现有的实例来创建新实例,而不是通过构造函数。
-
结构型模式(Structural Patterns):这些模式关注类和对象的组合,帮助确保系统中的组件可以组合成更复杂的结构。常见的结构型模式包括:
- 适配器模式(Adapter Pattern):将一个类的接口转换成客户端所期望的另一种接口。
- 桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们可以独立变化。
- 装饰器模式(Decorator Pattern):动态地给一个对象添加一些额外的职责。
- 外观模式(Facade Pattern):为子系统中的一组接口提供一个一致的界面,使子系统更易使用。
- 享元模式(Flyweight Pattern):通过共享大量细粒度的对象来有效地支持大量的对象。
- 组合模式(Composite Pattern):将对象组合成树形结构以表示部分-整体层次结构。
-
行为型模式(Behavioral Patterns):这些模式关注对象之间的交互和职责分配。关注对象之间的通信,譬如将行为、数据、展示拆分又互相通信的MVC架构,经典MVC模式中,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。其中,View的定义比较清晰,就是用户界面。
常见的行为型模式包括:- 策略模式(Strategy Pattern):定义一系列算法,将每一个算法封装起来,并使它们可以互相替换。
- 观察者模式(Observer Pattern):定义对象间一对多的依赖关系,以便当一个对象的状态改变时,所有依赖于它的对象都会得到通知并自动更新。
- 迭代器模式(Iterator Pattern):提供一种方法顺序访问一个集合对象中的各个元素,而不暴露该对象的内部表示。
- 模板方法模式(Template Method Pattern):定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
- 状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为。
- 命令模式(Command Pattern):将请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化、排队请求或记录请求日志。
- 责任链模式(Chain of Responsibility Pattern):使多个对象有机会处理请求,从而避免请求发送者和接收者之间的耦合。
框架、设计模式这两个概念总容易被混淆,其实它们之间还是有区别的。框架通常是代码重用,而设计模式是设计重用,架构则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。
在软件生产中有三种级别的重用:(1)内部重用,即在同一应用中能公共使用的抽象块;(2)代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;(2)应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。
3. 设计模式的优点
- 提高代码复用:通过模式化的解决方案,可以在不同的项目中重复使用相同的设计。
- 提高代码灵活性:设计模式使系统具有更好的扩展性和灵活性,便于在需求变化时进行调整。
- 促进团队合作:标准化的设计模式可以让团队成员更容易理解和维护代码,提高团队的沟通效率。
- 简化设计过程:通过提供通用的解决方案,设计模式可以帮助开发人员解决复杂的设计问题。
开发人员的共同平台
:提供了一个标准的术语系统,且具体到特定的情景。例如,单例设计模式意味着使用单个对象,这样所有熟悉单例设计模式的开发人员都能使用单个对象,并且可以通过这种方式告诉对方,程序使用的是单例模式。最佳的实践
:设计模式已经经历了很长一段时间的发展,它们提供了软件开发过程中面临的一般问题的最佳解决方案。学习这些模式有助于经验不足的开发人员通过一种简单快捷的方式来学习软件设计。
4. 设计模式的实践
- 学习经典书籍:如《设计模式:可复用面向对象软件的基础》(Erich Gamma 等著),这是设计模式的经典参考书。
- 应用到实际项目中:在实际项目中尝试应用设计模式,逐步理解其优势和适用场景。
- 分析开源项目:阅读和分析开源项目的设计,了解如何在实际中应用设计模式。
分享下个人的一些资料:《23种设计模式(C++完整版).pdf》,来自于网络,链接如下
链接:https://pan.baidu.com/s/1M2A9S6WKJ3_7BZipYd1SzQ
提取码:ch3q
--来自百度网盘超级会员V6的分享
程杰《大话设计模式》一书,使用JAVA编写示例程序,但是会C++的话,是可以看懂这些例程的,面向对象的这些语法二者很相似,我是买了一本二手书进行学习的。安利一个买正版二手书的微信小程序《多抓鱼》,不是广告,单纯觉得好用分享给大家
二、单例模式
单例模式(Singleton Pattern)是一种设计模式,其主要目的是确保一个类只有一个实例,并提供全局访问点。它通常用于需要全局唯一实例的场景,比如数据库连接池、配置管理器等。
1. 单例模式的关键点
- 唯一性: 确保类只有一个实例。
- 全局访问: 提供全局访问点来获取该实例。
- 延迟初始化: (可选)在第一次使用时才创建实例。
2. 单例模式的实现方式
单例模式有多种实现方式,下面列出了几种常见的方法。
饿汉式单例(Eager Initialization)
特点: 类加载时即创建实例,不管是否使用。简单且线程安全,但可能导致资源浪费。
class Singleton {
public:
static Singleton* getInstance() {
return instance;
}
private:
Singleton() {}
static Singleton* instance;
};
// 类加载时即创建实例
Singleton* Singleton::instance = new Singleton();
懒汉式单例(Lazy Initialization)
特点: 在第一次使用时创建实例。需要注意线程安全问题。
class Singleton {
public:
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
private:
Singleton() {}
static Singleton* instance;
};
// 类外定义静态成员
Singleton* Singleton::instance = nullptr;
双重检查锁定(Double-Checked Locking)
特点: 在懒汉式基础上加锁,避免了多线程环境下的同步开销。
#include <mutex>
class Singleton {
public:
static Singleton* getInstance() {
if (instance == nullptr) {
std::lock_guard<std::mutex> lock(mutex);
if (instance == nullptr) {
instance = new Singleton();
}
}
return instance;
}
private:
Singleton() {}
static Singleton* instance;
static std::mutex mutex;
};
// 类外定义静态成员
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;
登记式单例(Registry-based Singleton)
特点: 使用静态成员注册实例,避免了静态初始化顺序问题,但有额外的复杂性。
#include <map>
#include <string>
class Singleton {
public:
static Singleton* getInstance(const std::string& name) {
if (instances.find(name) == instances.end()) {
instances[name] = new Singleton();
}
return instances[name];
}
private:
Singleton() {}
static std::map<std::string, Singleton*> instances;
};
// 类外定义静态成员
std::map<std::string, Singleton*> Singleton::instances;
枚举式单例(Enum-based Singleton)
特点: 使用枚举类创建单例,线程安全且简单,但不支持延迟初始化。
#include <iostream>
class Singleton {
public:
// 获取单例实例
static Singleton& getInstance() {
return instance;
}
// 示例方法
void showMessage() const {
std::cout << "Hello, Singleton!" << std::endl;
}
private:
// 构造函数是私有的,防止直接创建实例
Singleton() {
std::cout << "Singleton instance created." << std::endl;
}
// 析构函数是私有的,防止删除实例
~Singleton() {
std::cout << "Singleton instance destroyed." << std::endl;
}
// 删除拷贝构造函数和赋值操作符
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 枚举成员,强制创建单例实例
enum { InstanceID };
static Singleton instance;
};
// 静态成员初始化
Singleton Singleton::instance;
int main() {
// 获取单例实例
Singleton& singleton1 = Singleton::getInstance();
singleton1.showMessage();
// 尝试获取另一个单例实例
Singleton& singleton2 = Singleton::getInstance();
singleton2.showMessage();
// 检查两个实例是否相同
if (&singleton1 == &singleton2) {
std::cout << "Both instances are the same." << std::endl;
} else {
std::cout << "Instances are different." << std::endl;
}
return 0;
}
3. 单例模式的优缺点
优点:
- 节省资源: 确保只有一个实例,避免了多次创建。
- 全局访问: 提供了全局访问点,方便管理。
缺点:
- 难以测试: 单例模式会使得单元测试变得复杂,因为它在多个测试中共享状态。
- 线程安全问题: 在多线程环境中,需要特别注意线程安全。
- 违背单一职责原则: 单例类同时负责创建和管理自身实例,可能导致设计上的问题。
总的来说,单例模式在适当的场景下非常有效,但需要谨慎使用,特别是在多线程和测试方面。
4. 示例程序
单例模式(Singleton Pattern)确保一个类只有一个实例,并提供一个全局访问点。以下是一个使用 C++ 实现单例模式的完美示例代码:
#include <iostream>
#include <mutex>
class Singleton {
public:
// 删除拷贝构造函数和赋值操作符,以防止复制
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 获取 Singleton 实例的静态方法
static Singleton& getInstance() {
static Singleton instance; // 局部静态变量,保证线程安全
return instance;
}
// 示例方法
void showMessage() const {
std::cout << "Hello, Singleton!" << std::endl;
}
private:
// 构造函数是私有的,防止直接创建实例
Singleton() {
std::cout << "Singleton instance created." << std::endl;
}
// 析构函数是私有的,防止删除实例
~Singleton() {
std::cout << "Singleton instance destroyed." << std::endl;
}
};
int main() {
// 获取单例实例
Singleton& singleton1 = Singleton::getInstance();
singleton1.showMessage();
// 尝试获取另一个单例实例
Singleton& singleton2 = Singleton::getInstance();
singleton2.showMessage();
// 检查两个实例是否相同
if (&singleton1 == &singleton2) {
std::cout << "Both instances are the same." << std::endl;
} else {
std::cout << "Instances are different." << std::endl;
}
return 0;
}
- 构造函数和析构函数:构造函数和析构函数是私有的,这样可以防止外部直接创建或销毁实例。
- 静态方法
getInstance
:这是获取单例实例的唯一方法。静态局部变量instance
确保在程序生命周期内只有一个Singleton
实例。这个静态变量会在第一次调用getInstance
时创建,并在程序结束时自动销毁。 - 删除拷贝构造函数和赋值操作符:为了防止拷贝和赋值操作,我们将拷贝构造函数和赋值操作符声明为
delete
。 - 线程安全:在 C++11 及以后的版本中,局部静态变量的初始化是线程安全的,因此我们不需要额外的同步机制。对于旧版本的 C++,可以使用互斥量来确保线程安全。
示例程序运行结果:
Singleton instance created.
Hello, Singleton!
Hello, Singleton!
Both instances are the same.
这个示例展示了单例模式的核心要点,并确保了代码的线程安全性和实例唯一性。
三、工厂模式
工厂模式是一种创建对象的设计模式,旨在通过提供一个创建对象的接口,使得子类可以决定实例化的类。工厂模式可以分为几个主要类型:简单工厂模式、工厂方法模式和抽象工厂模式。以下是对这些模式的详细介绍:
1. 简单工厂模式
简单工厂模式通过一个工厂类负责创建不同类型的对象,客户端只需调用工厂方法,而不需要知道具体类的实现。
特点:
- 封装对象创建:客户端只需了解工厂接口,而不需要了解具体的类。
- 降低系统耦合度:客户端与具体产品解耦,便于维护和扩展。
示例代码:
假设我们要创建一个简单的文档管理系统,其中有两种类型的文档:PDFDocument
和 WordDocument
。我们可以使用简单工厂模式来创建这些文档。
#include <iostream>
#include <string>
//定义产品接口->定义工厂类->使用工厂类
//1、首先,我们定义一个文档接口 `Document`,以及两个具体的文档类 `PDFDocument` 和 `WordDocument`
// 产品接口
class Document {
public:
virtual void open() const = 0; // 打开文档
virtual ~Document() = default;
};
// 具体产品:PDF 文档
class PDFDocument : public Document {
public:
void open() const override {
std::cout << "Opening PDF document" << std::endl;
}
};
// 具体产品:Word 文档
class WordDocument : public Document {
public:
void open() const override {
std::cout << "Opening Word document" << std::endl;
}
};
//2、接着,我们定义一个工厂类 `DocumentFactory`,它负责根据类型创建不同的文档实例。
// 工厂类
class DocumentFactory {
public:
// 工厂方法:根据文档类型创建相应的文档对象
static Document* createDocument(const std::string& type) {
if (type == "PDF") {
return new PDFDocument();
} else if (type == "Word") {
return new WordDocument();
} else {
std::cerr << "Error: Unsupported document type" << std::endl;
return nullptr;
}
}
};
//最后,我们在客户端代码中使用 `DocumentFactory` 来创建和操作文档对象。
int main() {
// 创建 PDF 文档
Document* pdfDoc = DocumentFactory::createDocument("PDF");
if (pdfDoc) {
pdfDoc->open();
delete pdfDoc; // 记得释放内存
}
// 创建 Word 文档
Document* wordDoc = DocumentFactory::createDocument("Word");
if (wordDoc) {
wordDoc->open();
delete wordDoc; // 记得释放内存
}
// 尝试创建不支持的文档类型
Document* unknownDoc = DocumentFactory::createDocument("Unknown");
if (unknownDoc) {
unknownDoc->open();
delete unknownDoc; // 不会被调用,因为创建失败
}
return 0;
}
- 产品接口 (
Document
): 定义了文档的基本操作open()
,确保所有具体产品都实现这个接口。 - 具体产品 (
PDFDocument
和WordDocument
): 实现了Document
接口的具体文档类型。 - 工厂类 (
DocumentFactory
): 提供静态方法createDocument
来创建不同类型的文档实例,并根据类型选择具体的产品。 - 客户端代码: 通过调用
DocumentFactory::createDocument
来获取所需的文档实例,并调用其方法。注意,客户端代码负责释放创建的文档对象以防内存泄漏。
这个示例展示了如何使用简单工厂模式来管理对象的创建,隐藏了具体的类实现细节,使得客户端代码与具体的产品解耦。
缺点:
- 违反开放-关闭原则:新增产品时需要修改工厂类。
- 产品等级过多:工厂类可能变得庞大复杂。
2. 工厂方法模式
工厂方法模式通过定义一个接口来创建对象,而将具体的创建过程延迟到子类中。每个子类负责自己的产品创建。
特点:
- 遵循开放-关闭原则:可以通过增加新的工厂子类来支持新的产品,而不需修改现有代码。
- 增加灵活性和扩展性:各个具体工厂之间的依赖较小。
示例代码:
假设我们仍然使用文档管理系统的例子,但这次我们将使用工厂方法模式来创建文档。我们会定义一个工厂接口,每个具体的工厂子类负责创建特定类型的文档。
#include <iostream>
#include <string>
//定义产品接口->定义工厂接口->定义具体工厂->使用工厂方法模式
//1、首先,我们定义一个文档接口 Document,以及两个具体的文档类 PDFDocument 和 WordDocument。
// 产品接口
class Document {
public:
virtual void open() const = 0; // 打开文档
virtual ~Document() = default;
};
// 具体产品:PDF 文档
class PDFDocument : public Document {
public:
void open() const override {
std::cout << "Opening PDF document" << std::endl;
}
};
// 具体产品:Word 文档
class WordDocument : public Document {
public:
void open() const override {
std::cout << "Opening Word document" << std::endl;
}
};
//2、定义一个抽象的工厂接口 `DocumentFactory`,声明一个工厂方法 `createDocument`,用于创建
// `Document` 对象。
// 工厂接口
class DocumentFactory {
public:
virtual Document* createDocument() const = 0; // 工厂方法
virtual ~DocumentFactory() = default;
};
//3、实现具体的工厂类,每个工厂负责创建特定类型的文档。
// 具体工厂:PDF 文档工厂
class PDFDocumentFactory : public DocumentFactory {
public:
Document* createDocument() const override {
return new PDFDocument();
}
};
// 具体工厂:Word 文档工厂
class WordDocumentFactory : public DocumentFactory {
public:
Document* createDocument() const override {
return new WordDocument();
}
};
//4、在客户端代码中,使用不同的工厂来创建和操作不同类型的文档。
int main() {
// 创建 PDF 文档的工厂
DocumentFactory* pdfFactory = new PDFDocumentFactory();
Document* pdfDoc = pdfFactory->createDocument();
if (pdfDoc) {
pdfDoc->open();
delete pdfDoc; // 记得释放内存
}
delete pdfFactory; // 释放工厂对象
// 创建 Word 文档的工厂
DocumentFactory* wordFactory = new WordDocumentFactory();
Document* wordDoc = wordFactory->createDocument();
if (wordDoc) {
wordDoc->open();
delete wordDoc; // 记得释放内存
}
delete wordFactory; // 释放工厂对象
return 0;
}
- 产品接口 (
Document
): 定义了文档的基本操作open()
。 - 具体产品 (
PDFDocument
和WordDocument
): 实现了Document
接口的具体文档类型。 - 工厂接口 (
DocumentFactory
): 声明了一个工厂方法createDocument
,用于创建Document
对象。 - 具体工厂 (
PDFDocumentFactory
和WordDocumentFactory
): 实现了工厂接口,提供具体的产品实例。 - 客户端代码: 使用具体的工厂来创建文档对象,并调用其方法。客户端代码只依赖于工厂接口,而不关心具体的文档类型,实现了高度的解耦。
通过工厂方法模式,你可以轻松扩展支持更多类型的文档,只需要增加新的产品和对应的工厂类,而不需要修改客户端代码。这种方式提高了系统的可扩展性和灵活性。
3. 抽象工厂模式
抽象工厂模式提供一个接口,用于创建相关或依赖的对象,而无需指定具体类。它一般用于创建一系列相关联的产品。
特点:
- 可以创建一组相关的产品:产品之间有一定的关系,如同一个系列的 GUI 组件。
- 遵循开放-关闭原则:可以添加新的产品系列,而无需修改现有代码。
示例代码1:
// 产品接口
class Button {
public:
virtual void render() = 0;
};
class WinButton : public Button {
public:
void render() override {
// Windows 风格按钮
}
};
class MacButton : public Button {
public:
void render() override {
// Mac 风格按钮
}
};
class Checkbox {
public:
virtual void paint() = 0;
};
class WinCheckbox : public Checkbox {
public:
void paint() override {
// Windows 风格复选框
}
};
class MacCheckbox : public Checkbox {
public:
void paint() override {
// Mac 风格复选框
}
};
// 抽象工厂
class GUIFactory {
public:
virtual Button* createButton() = 0;
virtual Checkbox* createCheckbox() = 0;
};
// 具体工厂
class WinFactory : public GUIFactory {
public:
Button* createButton() override {
return new WinButton();
}
Checkbox* createCheckbox() override {
return new WinCheckbox();
}
};
class MacFactory : public GUIFactory {
public:
Button* createButton() override {
return new MacButton();
}
Checkbox* createCheckbox() override {
return new MacCheckbox();
}
};
// 使用
GUIFactory* factory = new WinFactory();
Button* button = factory->createButton();
button->render();
示例代码2:
#include <iostream>
#include <string>
//定义产品接口->定义抽象工厂接口->定义具体工厂->使用抽象工厂模式
//1、首先,我们定义两个产品接口:`Document` 和 `DocumentView`,以及它们的具体实现。
// 文档接口
class Document {
public:
virtual void open() const = 0; // 打开文档
virtual ~Document() = default;
};
// 视图接口
class DocumentView {
public:
virtual void render() const = 0; // 渲染视图
virtual ~DocumentView() = default;
};
// 具体产品:PDF 文档
class PDFDocument : public Document {
public:
void open() const override {
std::cout << "Opening PDF document" << std::endl;
}
};
// 具体产品:Word 文档
class WordDocument : public Document {
public:
void open() const override {
std::cout << "Opening Word document" << std::endl;
}
};
// 具体视图:PDF 视图
class PDFDocumentView : public DocumentView {
public:
void render() const override {
std::cout << "Rendering PDF view" << std::endl;
}
};
// 具体视图:Word 视图
class WordDocumentView : public DocumentView {
public:
void render() const override {
std::cout << "Rendering Word view" << std::endl;
}
};
//2、接着,我们定义一个抽象工厂接口 `DocumentFactory`,用于创建一系列相关的文档和视图对象。
// 抽象工厂接口
class DocumentFactory {
public:
virtual Document* createDocument() const = 0; // 创建文档
virtual DocumentView* createView() const = 0; // 创建视图
virtual ~DocumentFactory() = default;
};
//3、实现具体的工厂类,每个工厂负责创建特定类型的文档和视图对象。
// 具体工厂:PDF 工厂
class PDFFactory : public DocumentFactory {
public:
Document* createDocument() const override {
return new PDFDocument();
}
DocumentView* createView() const override {
return new PDFDocumentView();
}
};
// 具体工厂:Word 工厂
class WordFactory : public DocumentFactory {
public:
Document* createDocument() const override {
return new WordDocument();
}
DocumentView* createView() const override {
return new WordDocumentView();
}
};
//4、在客户端代码中,使用不同的工厂来创建和操作不同类型的文档和视图。
int main() {
// 创建 PDF 工厂
DocumentFactory* pdfFactory = new PDFFactory();
Document* pdfDoc = pdfFactory->createDocument();
DocumentView* pdfView = pdfFactory->createView();
if (pdfDoc) {
pdfDoc->open();
delete pdfDoc; // 记得释放内存
}
if (pdfView) {
pdfView->render();
delete pdfView; // 记得释放内存
}
delete pdfFactory; // 释放工厂对象
// 创建 Word 工厂
DocumentFactory* wordFactory = new WordFactory();
Document* wordDoc = wordFactory->createDocument();
DocumentView* wordView = wordFactory->createView();
if (wordDoc) {
wordDoc->open();
delete wordDoc; // 记得释放内存
}
if (wordView) {
wordView->render();
delete wordView; // 记得释放内存
}
delete wordFactory; // 释放工厂对象
return 0;
}
- 产品接口 (
Document
和DocumentView
): 定义了文档和视图的基本操作。 - 具体产品 (
PDFDocument
、WordDocument
、PDFDocumentView
和WordDocumentView
): 实现了这些接口的具体类。 - 抽象工厂接口 (
DocumentFactory
): 定义了创建相关产品的方法createDocument
和createView
。 - 具体工厂 (
PDFFactory
和WordFactory
): 实现了抽象工厂接口,负责创建特定类型的文档和视图。 - 客户端代码: 通过工厂接口创建不同类型的文档和视图,确保了产品之间的兼容性和一致性。
通过抽象工厂模式,客户端代码可以在不改变现有代码的情况下,灵活地添加新的文档和视图类型,同时保持了创建过程的一致性。这种模式提高了系统的可扩展性和灵活性。
4. 使用场景
- 简单工厂模式:适用于产品类型有限、变化较小的场合。
- 工厂方法模式:适合于产品种类较多,经常需要扩展的情况,支持可扩展设计。
- 抽象工厂模式:适用于需要创建一系列相关产品的场景,如跨平台 GUI 系统等。
工厂方法模式 vs. 抽象工厂模式关键差异:
-
单一 vs. 多重产品:
- 工厂方法模式: 主要用于创建单个产品类型的实例,适用于需要灵活地引入新的产品类型的场景。
- 抽象工厂模式: 用于创建多个相关的产品实例,适用于需要管理一系列产品(例如,多个产品族)的场景。
-
工厂层次:
- 工厂方法模式: 每个工厂方法只能创建一个产品,客户端代码依赖于具体工厂来获得不同的产品实例。
- 抽象工厂模式: 工厂接口提供了创建一系列相关产品的方法,客户端可以使用不同的抽象工厂来创建一系列产品,保证产品的兼容性。
-
扩展性:
- 工厂方法模式: 适合扩展单个产品的不同变体。
- 抽象工厂模式: 适合扩展多个产品族,确保各个产品之间的一致性。
总的来说,抽象工厂模式确实可以被看作是工厂方法模式的一个扩展,它在工厂方法模式的基础上增加了处理多个产品族的能力,使得系统能够更好地处理复杂的产品创建需求。
5. 总结
工厂模式通过将对象创建的逻辑与使用逻辑分离,提高了代码的可维护性和灵活性。根据需求的复杂性,可以选择不同类型的工厂模式来实现创造性和解耦设计。适当使用工厂模式可以极大地减少代码的耦合度和复杂度。
注:水平有限,欢迎各位在评论区指导交流!!!😁😁😁