Simple Factory의 가장 큰 단점 중 하나는 새로운 비즈니스 클래스를 추가 할 때 다른 브랜치 나 케이스를 수동으로 추가해야한다는 것인데, 이는 확장에 불편합니다. 다이나믹 팩토리와는 달리 등록 만하면 사용할 수 있습니다.
다이나믹 팩토리를 처음 살펴보면 다소 혼란 스러울 수 있습니다. 다음으로이 실용적인 도구를 다음 단계를 통해 분석합니다.
- 문자열을 키로 사용하고 생성 클래스의 함수 포인터를 값으로 사용합니다.이 전역 변수 맵 을 통해 생성 함수를 획득하여 객체를 생성합니다. 간단한 코드는 다음과 같습니다. 이 에디션을 이해하고 다이내믹 팩토리의 핵심을 이해하십시오.
#include <iostream>
#include <map>
#include <string>
using namespace std;
class Base {
};
class A : public Base {
public:
A() {
cout << "A" << endl; }
};
class B : public Base {
public:
B() {
cout << "B" << endl; }
};
Base* createA() {
return new A(); }
Base* createB() {
return new B(); }
// 定义一个函数指针返回类型
using ConcreteCreator = Base* (*)();
// key: type, value: 函数指针
std::map<string, ConcreteCreator> fac;
int main() {
// 注册
fac.insert({
"A", createA});
fac.insert({
"B", createB});
// 使用
auto it = fac.find("A");
if (it != fac.end()) {
Base* b = (it->second)(); // 相当于 Base* b = new A();
delete b;
}
return 0;
}
- 개선, 1에는 단점이 있습니다. 즉, 각각의 새로운 구현 클래스에 대해 생성 기능이 그에 따라 추가되어야하는데, 이는 실제로 단순한 팩토리보다별로 좋지 않습니다. 템플릿 함수로 대체하고 있으므로이 함수는 생략하겠습니다.
...
template <typename BASE, typename DERIVED>
BASE* create() {
return new DERIVED();
}
// 定义一个函数指针返回类型
using ConcreteCreator = Base* (*)();
// key: type, value: 函数指针
std::map<string, ConcreteCreator> fac;
int main() {
// 注册
fac.insert({
"A", create<Base, A>});
fac.insert({
"B", create<Base, B>});
..
- 1과 2를 이해 한 후 다음 코드를 살펴 보겠습니다.
#pragma once
#include <map>
#include <string>
using namespace std;
// 这里定义一个泛型单例类,专门用来生成派生类,并返回基类指针
template <typename Object, typename ConcreteObject>
class ConcreteCreator {
public:
static Object* createObject() {
return new ConcreteObject(); }
};
template <typename Object>
class Creator {
public:
//实例化,全局唯一
static Creator& Instance() {
static Creator<Object> instance;
return instance;
}
private:
Creator() {
}
~Creator() {
}
Creator(Creator&); // 不准拷贝
public:
using CreateObjectDelegate = Object* (*)(); //类型定义,关联第10行
using MapRegisterCreatorItem = std::map<std::string, CreateObjectDelegate>;
template <typename ConcreteObject>
void registerCreator(const std::string& _type) {
mConcreteCreators[_type] =
ConcreteCreator<Object, ConcreteObject>::createObject;
}
void unregisterAllCreators() {
mConcreteCreators.clear(); }
Object* createObject(const std::string& _type) {
typename MapRegisterCreatorItem::iterator type =
mConcreteCreators.find(_type);
if (type != mConcreteCreators.end()) {
CreateObjectDelegate create = type->second;
if (create != 0) return create();
}
//找不到就返回nullptr
return nullptr;
}
private:
MapRegisterCreatorItem mConcreteCreators; // 注册信息都存在这里
};
위의 코드는 많이 보이지만 사실 1에서 2로 내려 가서 이해하기 어렵지 않습니다. 또한 완료 후 사용하기 매우 편리합니다. 다음과 같이. 그리고 제네릭을 적용하여 모든 간단한 공장을 대체 할 수 있습니다.
class Base {
};
class A : public Base {
public:
A() {
cout << "A" << endl; }
};
class B : public Base {
public:
B() {
cout << "B" << endl; }
};
using CRT = Creator<Base>;
int main()
{
//注册
CRT &crt = CRT::Instance();
crt.registerCreator<A>("A");
crt.registerCreator<B>("B");
// 根据字符串获取对象
Base *b = crt.createObject("A");
delete b;
return 0;
}