解决使用工厂时的循环依赖关系



>我有以下配置要评估,并且正在使用工厂根据类型将对象获取到 MathOperation 的子类。

    class MathOperation {
    Operation GetOperationType();
    int Evaluate (config c);
    }
    config {
      type = min
      config {
        type =  average
        int x 
        int y
     }
      config {
        type = sum 
        int p
        int q
     }
    ...
    }

例如,如果 x = 10, y = 20, p = 10, q = 2答案是最小(平均值(10, 20(, 总和(10, 2(( = 12。

我遇到了循环依赖问题,因为 MathOperation 的每个子类都需要包含工厂来评估它的子配置,而工厂 ofcoruse 需要包含 MathOperation 的每个子类。我该如何解决此问题?这是我目前拥有的:

MathOperationFactory.h 和 cc

#include "average.h"
#include "min.h"
#include "sum.h"
std::unique_ptr<MathOperationObject> MakeObject(OperationType type) {
switch(type) {
case min : return MinOperation();
...
}
}

MinOperation.h 和 cc

#include "mathoperationfactory.h"    
int Evaluate(Config c) {
int minimum = 1000; // large number.
ASSERT(config.type = min);
for(config : c) // repeated configs {
  type t = c.type;
  factory.MakeObject(t);
  if(t.Evaluate < minimum) {
 minimum = t;
}
}
return minimum;
}
工厂不需要

知道子类型,它只需要能够新建一个子类型。 一种方法是使用 Creator 类,该类的工作是将具体对象的创建委托回类本身。

我在这里使用std::string作为名称,但您可以轻松地使用intOperation枚举。

像这样:

#pragma once
#include <string> // 
#include <map>
#include <typeinfo>
class MathOperation;
/************************************************************************/
/* MathOperation           Factory                                      */
/************************************************************************/
// Abstract Interface Type For Creator
struct CMathOperationCreator
{
    virtual MathOperation* Create() = 0;
    virtual ~CMathOperationCreator() {}
};
// Creator Map
std::map<std::string, CMathOperationCreator*, StringLessNoCaseCHAR>& GetMathOperationFactoryMap();
// Templated concrete creator, to be registered in the header of the concrete mathop type
template<class Derived>
struct CMathOperationConcreteCreator: public CMathOperationCreator
{
    CMathOperationConcreteCreator(const std::string& theMathOperationTypeId)
    {
        auto aFactoryItem = GetMathOperationFactoryMap().find(theMathOperationTypeId);
        if(aFactoryItem != GetMathOperationFactoryMap().end())
        {
            if(typeid(*aFactoryItem->second) == typeid(*this)) // avoid duplicates
                return;
        }
        GetMathOperationFactoryMap()[theMathOperationTypeId] = this;
    }
    virtual MathOperation* Create() {return new Derived();}
};
//Factory Method
MathOperation* CreateMathOperation(const std::string& theMathOperationTypeId);
/**
* Macro to automatically register a MathOperation Type
*/
#define REGISTER_MathOperation( ConcreteMathOperation, name ) 
    static CMathOperationConcreteCreator<ConcreteMathOperation> ConcreteMathOperation##Creator(name);

CPP 文件:

// This is dumb, you don't have to do this, you just need a singleton factory that holds this map
std::map<std::string, CMathOperationCreator*, StringLessNoCaseCHAR>& GetMathOperationFactoryMap()
{
    static std::map<std::string, CMathOperationCreator*, StringLessNoCaseCHAR> theMap;
    return theMap;
}
MathOperation* CreateMathOperation( const std::string& theMathOperationTypeId )
{
    auto aFactoryItem = GetMathOperationFactoryMap().find(theMathOperationTypeId);
    if (aFactoryItem != GetMathOperationFactoryMap().end())
    {
        MathOperation* aObject = aFactoryItem->second->Create();
        return aObject;
    }
    return NULL;
}

注册课程:

class MinOperation : public MathOperation {
    Operation GetOperationType();
    int Evaluate (config c);
};
REGISTER_MathOperation(MinOperation, "min");
然后,在

分析令牌时,可以查询工厂中的操作:

MathOperation* pOp = CreateMathOperation(token.lowercase());

正如评论中指出的那样,如果没有看到真实的代码,很难确定。 但是,问题很可能是您在头文件中放置了太多包含。 如果您只是在 CC 文件中添加#include "mathoperationfactory.h",您应该没问题。

此外,您需要使用包括防护装置。

#pragma once确保

标头只包含一次。 始终将其作为标题中的第一行。

最新更新