前言
本篇文章正式带大家来学习C++中的设计模式,这篇文章主要带大家学习工厂模式。
一、什么是工厂模式
工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,但将具体对象的实例化延迟到子类或具体工厂类中。工厂模式通过解耦客户端代码和创建具体对象的过程,使客户端代码不需要直接依赖于具体对象的创建方式,而是通过工厂来创建对象,从而提高代码的灵活性和可维护性。
在C++中,工厂模式可以有多种实现方式,包括简单工厂模式、工厂方法模式和抽象工厂模式。
UML结构图:
二、简单工厂模式
简单工厂模式通过一个工厂类来封装对象的创建过程。客户端根据不同的参数传递给工厂类,工厂类根据参数的不同来创建不同的具体对象。简单工厂模式的一大优势是将对象的创建逻辑集中到一个工厂类中,客户端代码只需要与工厂类进行交互,而不需要直接与具体对象进行交互。
示例代码:
#include <iostream> using namespace std; // 抽象产品接口 class Product { public: virtual void use() = 0; }; // 具体产品类A class ConcreteProductA : public Product { public: void use() { cout << "Using ConcreteProductA\n"; } }; // 具体产品类B class ConcreteProductB : public Product { public: void use() { cout << "Using ConcreteProductB\n"; } }; //工厂类 class Factory { public: static Product* CreateProduct(int type) { if (type == 1) { return new ConcreteProductA(); } else if (type == 2) { return new ConcreteProductB(); } else { return NULL; } } }; int main(void) { Product* productA = Factory::CreateProduct(1); productA->use(); Product* productB = Factory::CreateProduct(2); productB->use(); delete productA; delete productB; return 0; }
三、简单工厂模式优点和缺点
优点:
将对象的创建逻辑集中到了一个工厂类中,客户端只需要与工厂类进行交互,而无需关注具体对象的创建过程,降低了客户端代码的复杂性。
客户端代码与具体对象解耦,可以通过工厂类创建不同的对象,而无需修改客户端代码,提高了代码的灵活性和可扩展性。
客户端代码只需要知道抽象产品接口,而无需了解具体产品的细节,实现了依赖倒置原则。
可以隐藏具体产品的实现细节,提高了代码的安全性。
缺点:
违反了开闭原则,对于每个新增的具体产品,都需要修改工厂类的创建逻辑,可能导致工厂类的代码过于臃肿。
工厂类集中了所有的对象创建逻辑,当有多个具体产品时,工厂类的代码会变得复杂,不易于维护和扩展。
简单工厂模式中的工厂类负责创建所有具体产品,当新增具体产品时,工厂类会变得臃肿,不符合单一职责原则。
四、简单工厂适用场景
1.对象的创建逻辑相对简单:当需要创建的对象逻辑比较简单,不涉及复杂的条件判断或算法时,可以使用简单工厂模式。
2.需要对客户端代码隐藏具体对象的创建细节:通过简单工厂模式,客户端只需要与工厂类进行交互,而不需要直接与具体对象进行交互,可以实现对具体对象的创建细节进行封装和隐藏。
3.需要根据不同的参数创建不同的对象:当需要根据不同的参数或配置来选择创建不同的具体对象时,可以使用简单工厂模式。客户端只需要给定相应的参数,工厂类根据参数的不同来创建对应的对象。
4.对象的数量相对稳定:如果系统中的对象数量固定且不经常变化,不需要频繁地添加新的具体对象,简单工厂模式可以简化对象的创建和管理。
五、简单工厂类的使用
在Qt中,使用工厂模式可以实现创建和管理各种对象的过程,尤其在UI编程中非常常见。以下是一个简单的示例,展示了如何在Qt中使用工厂模式来创建不同类型的窗口:
首先,我们需要定义一个抽象窗口类(AbstractWindow)作为工厂的产品接口,用于表示不同类型的窗口对象。
class AbstractWindow : public QWidget { public: virtual void display() = 0; };
接下来,我们可以创建具体的窗口类(例如:MainWindow、DialogWindow、PopupWindow)继承自抽象窗口类,并实现其相应的方法。
class MainWindow : public AbstractWindow { public: void display() override { // 实现MainWindow的显示逻辑 } }; class DialogWindow : public AbstractWindow { public: void display() override { // 实现DialogWindow的显示逻辑 } }; class PopupWindow : public AbstractWindow { public: void display() override { // 实现PopupWindow的显示逻辑 } };
接下来,我们需要创建一个窗口工厂类(WindowFactory),用于根据不同的参数创建相应类型的窗口对象。
class WindowFactory { public: static AbstractWindow* createWindow(const QString& windowType) { if (windowType == "MainWindow") { return new MainWindow(); } else if (windowType == "DialogWindow") { return new DialogWindow(); } else if (windowType == "PopupWindow") { return new PopupWindow(); } return nullptr; } };
在客户端代码中,我们可以使用窗口工厂类来创建具体的窗口对象。
QString windowType = "MainWindow"; // 可以根据需求指定不同的窗口类型 AbstractWindow* window = WindowFactory::createWindow(windowType); if (window) { window->display(); delete window; }
通过上述代码,我们可以根据不同的窗口类型使用工厂模式创建相应的窗口对象,并执行其特定的显示逻辑。
在这个例子中,抽象窗口类充当了工厂的产品接口,具体窗口类是工厂所创建的产品,而窗口工厂类则是具体实现工厂模式的类。通过使用工厂模式,我们能够有效地解耦了窗口对象的创建和使用过程,并使得程序更具灵活性和可扩展性。
总结
本篇文章就讲解到这里。