文章目录
- 抽象基类、工厂方法
- 扩展工厂
抽象基类、工厂方法
renderer.h
#ifndef UNTITLED_RENDERER_H
#define UNTITLED_RENDERER_H#include <string>
class IRenderer {
public:virtual ~IRenderer() {}virtual bool func1(const std::string& filename) = 0;virtual void Render() = 0;
};
#endif //UNTITLED_RENDERER_H
rendererfactory.h
#ifndef UNTITLED_RENDERERFACTORY_H
#define UNTITLED_RENDERERFACTORY_H
#include "renderer.h"
#include "string"
class RendererFactory {
public:IRenderer* CreateRenderer(const std::string& type); // 返回派生类对象实例
};
#endif //UNTITLED_RENDERERFACTORY_H
rendererfactory.cpp
#include "rendererfactory.h"
#include 其他派生类的.h
//IRenderer* Render
IRenderer *RendererFactory::CreateRenderer(const std::string &type) {if (type == "opengl") {return new OpenGlRenderer();} else if (type == "directx") {return new DirectxRenderer();} else {return new MesaRenderer();}return NULL;
}
工厂方法能够返回IRenderer
的3个派生类的任意一个,取决于输入字符串,这意味着能够基于用户输入或根据运行时读入的配置文件创建不同的类。各个派生类的头文件为私有头文件,仅仅包含在工厂.cpp中,不需要随着API一起发布。
该方法的缺点:
包含了可用的派生类的硬编码信息,若需要为系统添加新的渲染器,则必须修改rendererfactory.cpp
扩展工厂
为了将具体的派生类你和工厂方法解耦,并支持在运行时添加新的派生类,可以这样修改工厂类:
1、工厂类维护一个银蛇,将类型名与创建对象的回调关联起来
2、允许新的派生类以一对新的方法调用来实现注册和注销
3、运行时注册新类的能力允许工厂方法为API创建可以扩展的插件接口
4、工厂对象必须保存状态信息,因此最好强制要求任意时刻只能创建一个工厂对象,简洁起见,使用静态方法/变量实现
rendererfactory.h
//
// Created by hanhandi on 2022/8/18.
//#ifndef UNTITLED_RENDERERFACTORY_H
#define UNTITLED_RENDERERFACTORY_H
#include "renderer.h"
#include "string"
#include "map"class RendererFactory {
public:
// IRenderer* CreateRenderer(const std::string& type); // 返回派生类对象实例typedef IRenderer* (*CreateCallback) ();static void RegisterRender(const std::string& type, CreateCallback cb);static void UnregisterRender(const std::string& type);static IRenderer* CreateRender(const std::string& type);
private:typedef std::map<std::string, CreateCallback> CallbackMap;static CallbackMap mRenderers;
};
#endif //UNTITLED_RENDERERFACTORY_H
rendererfactory.cpp
//
// Created by hanhandi on 2022/8/18.
//
#include "rendererfactory.h"// 在RendererFactory 中实例化静态变量
RendererFactory::CallbackMap RendererFactory::mRenderers;void RendererFactory::RegisterRender(const std::string &type, CreateCallback cb) {mRenderers[type] = cb;
}void RendererFactory::UnregisterRender(const std::string &type) {mRenderers.erase(type);
}IRenderer *RendererFactory::CreateRender(const std::string &type) {CallbackMap::iterator it = mRenderers.find(type);if (it != mRenderers.end()) {// 调用回调以构造此派生类型的对象return (it->second)();}return NULL;
}
在main函数中我们进行新类的注册:
main.cpp
#include <iostream>
#include "rendererfactory.h"class UserRenderer : public IRenderer
{
public:~UserRenderer() {}bool func1(const std::string& filename) { return true; }void Render() { }static IRenderer* Create() { return new UserRenderer(); }
};
int main() {// 注册一个新的渲染器RendererFactory::RegisterRender("user", UserRenderer::Create);// 为新渲染器创建实例IRenderer* r = RendererFactory::CreateRender("user");r->Render();delete r;std::cout << "Hello, World!" << std::endl;return 0;
}
主要注意的地方:
static IRenderer* Create() { return new UserRenderer(); }
是新类新添加的函数,在工厂的注册函数中需要接受返回对象的回调。