首页 > 解决方案 > 工厂设计模式优化

问题描述

Creation在 Creation.cc 和 Creation.h 中都有一个名为的类,并且有一堆createA, createB, createC... 等。这个类中的函数,它们都将返回一个指针类型。

我有很多modelA.cc,modelB.cc,modelC.cc ...等。文件,并且所有文件都包含 Creation.h。

因为每当我制作一个新模型x(制作一个新的modelx.cc)时,我需要createx在Creation.h中添加相应的,这将使所有model.cc文件重新编译。

所有createA, createB,createC函数都有相同的参数列表,但输入值和实现不同,这基于它们的 model.cc。

我的目标是我不想在添加新createx函数时重新编译所有 model.cc。

谢谢。

标签: c++design-patternsfactory-pattern

解决方案


一个常见的策略是让工厂包含一个注册方法。一旦注册了一个类,就会调用工厂来获取一个实际的实例。

下面的 C++17 示例允许“接口”的子类在创建调用中具有不同的参数。“createInstance”的任务是为特定类构造一个实例。

Any 类取自这里。如链接中所述, createInstance 调用对匹配方法签名的输入参数非常特别。

#include <iostream>
#include <functional>
#include <map>
#include <string>
#include <any>
#include <functional>
#include <map>
#include <string>
#include <iostream>

struct interface
{
};


template<typename Ret>
struct AnyCallable
{
    AnyCallable() {}
    template<typename F>
    AnyCallable(F&& fun) : AnyCallable(std::function(fun)) {}
    template<typename ... Args>
    AnyCallable(std::function<Ret(Args...)> fun) : m_any(fun) {}
    template<typename ... Args>
    Ret operator()(Args&& ... args) 
    { 
        return std::invoke(std::any_cast<std::function<Ret(Args...)>>(m_any), std::forward<Args>(args)...); 
    }
    std::any m_any;
};

struct factory
{
   std::map<std::string,  AnyCallable<interface>> registry;
   void registerClass(std::string const & class_name, AnyCallable<interface> function)
   {
      registry[class_name] = function;
   }

   template<typename ... Args>
   interface createInstance(std::string const & class_name, Args && ... args)
   {
      if(registry.find(class_name) == registry.end())
      {
         throw "No class found";
      }
      return registry[class_name](std::forward<Args>(args)...); 
   }
};


struct A:public interface
{
   A() 
   {
      std::cout << "Create A" << std::endl;
   }

   static interface createInstance(int t)
   {
      return A();
   } 

   static void registerWithFactory(factory& f)
   {
      f.registerClass("A",&createInstance);
   }
};


struct B:public interface
{
   B() 
   {
      std::cout << "Create B" << std::endl;
   }

   static interface createInstance(std::tuple<int, double> t)
   {
      return B();
   } 

   static void registerWithFactory(factory& f)
   {
      f.registerClass("B",&createInstance);
   }
};

int main(int argc, char* argv[])
{
    factory f;

    A::registerWithFactory(f);
    B::registerWithFactory(f);
    try {
        interface a = f.createInstance("A",1);
        interface b = f.createInstance("B",std::tuple{1,1.0});
        interface c = f.createInstance("C");
    }
    catch(...)
    {
       std::cout << "createInstance failed" << std::endl;
    }
    return 0;
}

工厂的所有成员都将从“界面”下降。“工厂”将允许注册尚未创建的新类。在示例中,A 和 B 存在,但 C 不存在。将来可以在不重新编译现有代码的情况下添加 C。

有多种模式可以扩展此主题。


推荐阅读