工厂模式(正式)

抽象工厂模式及示例

模式的动机

  1. 提供一种接口,用于创建一系列相关或相互依赖的对象

  2. 抽象工厂模式通过引入抽象工厂接口,允许客户端代码通过工厂接口创建产品,而不需要关心具体的产品类;

    • 数据库之间的查询语句是差不多的,不用管是哪类数据库
  3. 使得客户端代码可以与特定产品的具体类解耦,实现了抽象和实现的分离

    • 只需要在模板中填入已知的数据库名字

模式的实现

  1. 抽象的工厂和抽象的类,扩展的整体风格
    • 如平台 数据库种类都是整体,内部逻辑实际上差不多,都需要增删改查
  2. 抽象工厂模式的实现,一系列有相互依赖相互作用的对象组合的生成
    • 都需要基类继承,工厂调用,所需虚函数都差不多,都可以配合
  3. 抽象工厂模式的缺点是难以应对”新对象”的需求变动
    • 新的对象要求改变新的逻辑,比如在数据库增删改查之外加个莫名其妙的上传,基类和具体类和客户端都需要重写添加

我们设想这样一个情景:

  • 考虑两个平台: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渲染引擎、当频引擎等。抽象工厂式可用于创建适用于特定平台的游戏引擎组
posted @ 2023-09-24 14:48  游客0721  阅读(22)  评论(0)    收藏  举报