|
看了Modern C++ design,
写了一个对象工厂,和书中的不太一样,且还有许多不完整的地方。在实现时牺牲了动态注册产品的能力,但由于用数组保存关联,提高了创建对象的速度。
希望大家多给点意见。
文件:StaticFactory.h
[code:1]
#ifndef _STATIC_FACTORY_H
#define _STATIC_FACTORY_H
#include <Loki/Typelist.h>
#include <Loki/EmptyType.h>
#include <Loki/NullType.h>
template <typename Ptr, class TList, int Index >
struct InitHelper {
static void init(Ptr* ass) {
InitHelper<Ptr, TList, Index - 1>::init(ass - 1);
*ass = Loki::TL::TypeAt<TList, Index>::Result::create;
}
};
template <typename Ptr, class TList>
struct InitHelper<Ptr, TList, 0> {
static void init(Ptr* ass) {
*ass = Loki::TL::TypeAt<TList, 0>::Result::create;
}
};
template
<
class AbstractProduct,
class TList
>
class StaticFactory
{
public:
typedef typename Loki::TL::NoDuplicates<TList >::Result \
ProductTypelist;
typedef AbstractProduct*(*Creator)();
public:
StaticFactory() {
init();
}
AbstractProduct* createObject(int id) {
if(id < 0 || id >= size_)
return 0;
return associations_[id]();
}
template <class P>
AbstractProduct* createObject() {
int id = getProductId<P>();
if(id < 0 || id >= size_)
return 0;
return associations_[id]();
}
template <class P>
int getProductId() {
return Loki::TL::IndexOf<ProductTypelist, P>::value;
}
private:
void init() {
InitHelper
<
Creator,
ProductTypelist,
size_ -1
>::init(associations_ + (size_ -1));
}
enum {size_ = \
Loki::TL::Length<ProductTypelist>::value};
Creator associations_[size_];
};
#endif
[/code:1]
使用的例子:
[code:1]
#include "StaticFactory.h"
#include <iostream>
struct B
{
static B* create() {
std::cout << "B::create()" << std::endl;
return NULL;
};
};
struct D1 : public B
{
static B* create() {
std::cout << "D1::create()" << std::endl;
return NULL;
};
};
struct D2 : public B
{
static B* create() {
std::cout << "D2::create()" << std::endl;
return NULL;
};
};
struct D3 : public B
{
static B* create() {
std::cout << "D3::create()" << std::endl;
return NULL;
};
};
int main()
{
typedef TYPELIST_3(D1, D2, D3) myTypeList;
StaticFactory<B, myTypeList> factory;
factory.createObject(0);
factory.createObject(1);
factory.createObject(2);
factory.createObject<D1>();
factory.createObject<D2>();
factory.createObject<D3>();
return 0;
}
[/code:1] |
|