再说对外发布 SDK 中工厂模式的使用

一般而言,当我们使用工厂模式时,通常这么使用:

举例示例 1

renderer.h

#ifndef RENDERER_H
#define RENDERER_H

#include <string>

// An abstract interface for a 3D renderer.
class IRenderer {
public:
	virtual ~IRenderer() {}
	virtual bool LoadScene(const std::string &filename) = 0;
	virtual void SetViewportSize(int w, int h) = 0;
	virtual void SetCameraPos(double x, double y, double z) = 0;
	virtual void SetLookAt(double x, double y, double z) = 0;
	virtual void Render() = 0;
};

#endif

rendererfactory.h

#ifndef RENDERERFACTORY_H
#define RENDERERFACTORY_H

#include "renderer.h"
#include <string>

// A factory object that creates instances of different 3D renderers.
class RendererFactory {
public:
	// Create a new instance of a named 3D renderer.
	// type can be one of "opengl", "directx", or "mesa"
	IRenderer *CreateRenderer(const std::string &type);
};

#endif

rendererfactory.cpp

#include "rendererfactory.h"
#include <iostream>

using std::cout;
using std::endl;

class OpenGLRenderer : public IRenderer {
public:
	~OpenGLRenderer() {}
	bool LoadScene(const std::string &filename) { return true; }
	void SetViewportSize(int w, int h) {}
	void SetCameraPos(double x, double y, double z) {}
	void SetLookAt(double x, double y, double z) {}
	void Render() { cout << "OpenGL Render" << endl; }
};

class DirectXRenderer : public IRenderer {
public:
	bool LoadScene(const std::string &filename) { return true; }
	void SetViewportSize(int w, int h) {}
	void SetCameraPos(double x, double y, double z) {}
	void SetLookAt(double x, double y, double z) {}
	void Render() { cout << "DirectX Render" << endl; }
};

class MesaRenderer : public IRenderer {
public:
	bool LoadScene(const std::string &filename) { return true; }
	void SetViewportSize(int w, int h) {}
	void SetCameraPos(double x, double y, double z) {}
	void SetLookAt(double x, double y, double z) {}
	void Render() { cout << "Mesa Render" << endl; }
};

IRenderer *RendererFactory::CreateRenderer(const std::string &type)
{
	if (type == "opengl") {
		return new OpenGLRenderer;
	}
	if (type == "directx") {
		return new DirectXRenderer;
	}
	if (type == "mesa") {
		return new MesaRenderer;
	}
	return nullptr;
}

main.cpp

#include "rendererfactory.h"

int main(int, char **)
{
	// create the factory object
	RendererFactory *f = new RendererFactory;

	// create an OpenGL renderer
	IRenderer *ogl = f->CreateRenderer("opengl");
	ogl->Render();
	delete ogl;

	// create a Mesa software renderer
	IRenderer *mesa = f->CreateRenderer("mesa");
	mesa->Render();
	delete mesa;

	delete f;
	return 0;
}

当在模块内运行时,这么使用,是没有问题的。但当抽象出作为SDK发布给用户做二次开发使用,用户是感知不到.cpp文件的,这些不随 SDK(api)发布给用户使用,用户感知不到不同渲染器的私有细节,看不到不同渲染器的具体类型,用户只能通过字符串变量指定渲染器。

这个时候,如果想为系统添加新的渲染器是做不到的。这就需要将具体的派生类和工厂方法解耦,并支持在运行时添加新的派生类。可以采用如下方法进行:

让工厂类维护一个映射,此映射将类型名和创建对象的回调关联起来,然后就可以允许新的派生类通过一对新的方法调用来实现注册和注销。运行时注册新类的能力,允许工厂方法模式为 API 创建可扩展性的插件接口。

举例示例 2

renderer.h

#ifndef RENDERER_H
#define RENDERER_H

#include <string>

// An abstract interface for a 3D renderer.
class IRenderer {
public:
	virtual ~IRenderer() {}
	virtual bool LoadScene(const std::string &filename) = 0;
	virtual void SetViewportSize(int w, int h) = 0;
	virtual void SetCameraPos(double x, double y, double z) = 0;
	virtual void SetLookAt(double x, double y, double z) = 0;
	virtual void Render() = 0;
	virtual IRenderer *Create() = 0;
};

#endif

rendererfactory.h

#ifndef RENDERERFACTORY_H
#define RENDERERFACTORY_H

#include "renderer.h"
#include <string>
#include <map>

// A factory object that creates instances of different
// 3D renderers. New renderers can be dynamically added
// and removed from the factory object.
class RendererFactory {
public:
	// The type for the callback that creates an IRenderer instance
	typedef IRenderer* (*CreateCallback)();

	// Add a new 3D renderer to the system
	static void RegisterRenderer(const std::string &type, CreateCallback cb);
	
	// Remove an existing 3D renderer from the system
	static void UnregisterRenderer(const std::string &type);

	// Create an instance of a named 3D renderer
	static IRenderer *CreateRenderer(const std::string &type);

private:
	typedef std::map<std::string, CreateCallback> CallbackMap;
	static CallbackMap mRenderers;
};

#endif

rendererfactory.cpp

#include "rendererfactory.h"
#include <iostream>

// instantiate the static variable in RendererFactory
RendererFactory::CallbackMap RendererFactory::mRenderers;

void RendererFactory::RegisterRenderer(const std::string &type, CreateCallback cb)
{
	mRenderers[type] = cb;
}

void RendererFactory::UnregisterRenderer(const std::string &type)
{
	mRenderers.erase(type);
}

IRenderer *RendererFactory::CreateRenderer(const std::string &type)
{
	CallbackMap::iterator it = mRenderers.find(type);
	if (it != mRenderers.end()) {
		// call the creation callback to construct this derived type
		return (it->second)();
	}

	return nullptr;
}

main.cpp

#include "rendererfactory.h"
#include <iostream>

using std::cout;
using std::endl;

// An OpenGL-based 3D renderer
class OpenGLRenderer : public IRenderer
{
public:
	~OpenGLRenderer() {}
	bool LoadScene(const std::string &filename) { return true; }
	void SetViewportSize(int w, int h) {}
	void SetCameraPos(double x, double y, double z) {}
	void SetLookAt(double x, double y, double z) {}
	void Render() { cout << "OpenGL Render" << endl; }
	IRenderer *Create() { return new OpenGLRenderer; }
};

// A DirectX-based 3D renderer
class DirectXRenderer : public IRenderer
{
public:
	bool LoadScene(const std::string &filename) { return true; }
	void SetViewportSize(int w, int h) {}
	void SetCameraPos(double x, double y, double z) {}
	void SetLookAt(double x, double y, double z) {}
	void Render() { cout << "DirectX Render" << endl; }
	IRenderer *Create() { return new DirectXRenderer; }
};

// A Mesa-based software 3D renderer
class MesaRenderer : public IRenderer
{
public:
	bool LoadScene(const std::string &filename) { return true; }
	void SetViewportSize(int w, int h) {}
	void SetCameraPos(double x, double y, double z) {}
	void SetLookAt(double x, double y, double z) {}
	void Render() { cout << "Mesa Render" << endl; }
	IRenderer *Create() { return new MesaRenderer; }
};


int main(int, char **)
{
	// register the various 3D renderers with the factory object
	RendererFactory::RegisterRenderer("opengl", OpenGLRenderer::Create);
	RendererFactory::RegisterRenderer("directx", DirectXRenderer::Create);
	RendererFactory::RegisterRenderer("mesa", MesaRenderer::Create);

	// create an OpenGL renderer
	IRenderer *ogl = RendererFactory::CreateRenderer("opengl");
	ogl->Render();
	delete ogl;

	// create a Mesa software renderer
	IRenderer *mesa = RendererFactory::CreateRenderer("mesa");
	mesa->Render();
	delete mesa;

	// unregister the Mesa renderer
	RendererFactory::UnregisterRenderer("mesa");
	mesa = RendererFactory::CreateRenderer("mesa");
	if (! mesa)
	{
		cout << "Mesa renderer unregistered" << endl;
	}

	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值