工厂模式(正式)
抽象工厂模式及示例
模式的动机
-
提供一种接口,用于创建一系列相关或相互依赖的对象
-
抽象工厂模式通过引入抽象工厂接口,允许客户端代码通过工厂接口创建产品,而不需要关心具体的产品类;
- 数据库之间的查询语句是差不多的,不用管是哪类数据库
-
使得客户端代码可以与特定产品的具体类解耦,实现了抽象和实现的分离
- 只需要在模板中填入已知的数据库名字
模式的实现
- 抽象的工厂和抽象的类,扩展的整体风格
- 如平台 数据库种类都是整体,内部逻辑实际上差不多,都需要增删改查
- 抽象工厂模式的实现,一系列有相互依赖相互作用的对象组合的生成
- 都需要基类继承,工厂调用,所需虚函数都差不多,都可以配合
- 抽象工厂模式的缺点是难以应对”新对象”的需求变动
- 新的对象要求改变新的逻辑,比如在数据库增删改查之外加个莫名其妙的上传,基类和具体类和客户端都需要重写添加
我们设想这样一个情景:
- 考虑两个平台:Windows 和 MAC
- 有两个ui组件:
- PushButton : click, close;
- MainWindow : show, close;
- QT在UI控件中创建按钮对象,实际上这个按钮需要继承自很多基类,但是对于用户来说可能就是一行代码的事,实现了抽象与具体需求实现的分离
//该只是一个最基类,用来给不同的平台继承实现具体控件实现
class PushButton
{
public:
//定义为纯虚函数给子类重写
virtual void Click() = 0;
virtual void Close() = 0;
};
class MainWindow
{
public:
virtual void Show() = 0;
virtual void Close() = 0;
};
class GUIFactory
{
public:
//使用智能指针来管理对象的创建事,并且该工厂定义为抽象
virtual shared_ptr<PushButton> CreateButton() = 0;
virtual shared_ptr<MainWindow> CreateWindow() = 0;
};
这里定义了三个抽象类,PushButton 和 MainWindow 是 GUI 元素,GUIFactory 是用于创建这些元素的抽象工厂。
下面我们实现一下Windows下的实现:
#pragma once
//继承自基类实现其虚函数,抽象到具体的实现
#include "UI.h"
#include <iostream>
using namespace std;
class WindowsButton: public PushButton
{
public:
virtual void Click()
{
cout << "WindowsButton::Click" << endl;
}
virtual void Close()
{
cout << "WindowsButton::Close" << endl;
}
};
class WindowsWindow:public MainWindow
{
public:
virtual void Show()
{
cout << "WindowsWindow::Show" << endl;
}
virtual void Close()
{
cout << "WindowsWindow::Close" << endl;
}
};
class WindowsFactory: public GUIFactory
{
public:
virtual shared_ptr<PushButton> CreateButton()
{
return make_shared<WindowsButton>();
}
virtual shared_ptr<MainWindow> CreateWindow()
{ //返回创建的智能指针
return make_shared<WindowsWindow>();
}
};
上面就是一个Windows风格的实现,实际上,我们在按照上面Windows的方式扩充了Mac OS和Linux风格的实现之后,我们可以按照下面的方式在main函数中如何使用。
int main()
{
shared_ptr<GUIFactory> factory;
#ifdef _WIN32 // 宏Q_OS_WIN用于Windows系统
factory = make_shared<WindowsFactory>();
#elif __APPLE__ // 宏Q_OS_MAC用于MacOS系统
factory = make_shared<MacOSFactory>();
#elif __linux__// 宏Q_OS_LINUX用于Linux系统,包括Ubuntu
//factory = make_shared<UbuntuFactory>();
#else
factory = make_shared<DefaultFactory>();
#endif
// 这里是客户端的逻辑不受干扰,他知道类的名叫做factory,不知道具体叫什么
shared_ptr<GUIFactory> factory;
//创建一个工厂类实例,创建一个windows实例指针被基类指针指向
factory = make_shared<WindowsFactory>();
工厂基类指针由实现类的创建,windows实例指针的虚函数
shared_ptr<PushButton> button = factory->CreateButton();
shared_ptr<MainWindow> window = factory->CreateWindow();
button->Click();
button->Close();
window->Show();
window->Close();
}
总结:
- 很多中类型是数据库,需要通过一个navicat来进行统一操作,在客户端层面只需要知道数据库配置信息以及一些常见SQL就能正常使用,不需要具体关心数据库底层实现
- 数据库之间SQL逻辑差不多,可以由一个基类虚函数这些差不多的SQL逻辑给他们继承使用,然后使用工厂类接口统一创建,给他们继承工厂类在里面实现自己的逻辑,
- 上述要求数据库之间是相关的,如果多了一个新型数据库语言YQL,逻辑完全不同,那就智能重写基类和工厂方法和客户端的逻辑了,就不合适
模式的使用场景
- 图形用户界面库一套UI,不同操作系统下的按钮、文本框、窗口等控件可以使用见和行为的一致性,如QT的图形用户界面:不同的具体工厂来创建,以确保外2)数据库访问库需要根据不同的数居库系统(如MySQL、SQLite、Oracle) 提供不同的连接器和查询生成器:
- (PC、游戏机、移动设备)可能需要不同的图形
- 在游戏开发中,不同的游戏平台截图(Alt + A渲染引擎、当频引擎等。抽象工厂式可用于创建适用于特定平台的游戏引擎组

浙公网安备 33010602011771号