ダイナミックファクトリは、単純なファクトリを置き換えるのに最適な方法です

Simple Factoryの最大の欠点の1つは、新しいビジネスクラスを追加するときに、elseブランチまたはケースを手動で追加する必要があることです。これは、拡張に不便です。ダイナミックファクトリとは異なり、使用する前に登録するだけで済みます。
ダイナミックファクトリを最初に見たとき、少し混乱するかもしれませんが、次に、この実用的なツールを次の手順で分析します。

  1. 文字列をキー、作成クラスの関数ポインタを値として使用します。このグローバル変数マップを介して、オブジェクトを作成するための作成関数を取得します。簡略化したコードは次のとおりです。このエディションを理解し、ダイナミックファクトリの鍵を理解してください。
#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. 改善点として、1には欠点があります。つまり、新しい実装クラスごとに、それに応じてcreate関数を追加する必要があります。これは、実際には単純なファクトリよりもはるかに優れています。テンプレート関数に置き換えているため、この関数は省略します。
...
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. 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;	
}

おすすめ

転載: blog.csdn.net/niu91/article/details/109610888