使用模板库 class 消除工厂 class 派生 class 上的冗余的简洁方法
Clean way to use a template base class to eliminate redundancy on derived classes for a factory class
我正在尝试创建一个抽象工厂模式,其中我有两个工厂,我们称它们为 factoryA 和 factoryB。我将使用 struct 而不是 class 来节省一些输入。
对于一些继承的classes家族,让我们从一些class A开始,
struct A
{
// ...
};
struct derivedA1 : public A
{
// ...
};
struct derivedA2 : public derivedA1
{
// ...
};
为了便于说明,现在让我们对其他 class B 做同样的事情。
struct B
{
// ...
};
struct derivedB1 : public B
{
// ...
};
struct derivedB2 : public derivedB1
{
// ...
};
因此,对于这些 classes,我正在尝试创建一个工厂模式(请注意,在我的工作中,我们使用自定义错误处理,我将调用 error_handle_t,其实现无关紧要):
struct factoryA
{
std::map<int, std::shared_ptr<A> > myMap;
factoryA()
{
// setup values to search against
myMap[0] = std::make_shared<A>();
myMap[1] = std::make_shared<derivedA1>();
myMap[2] = std::make_shared<derivedA2>();
//...room for more
}
error_handle_t make_object(int key, std::shared_ptr<A>& object)
{
object = myMap[key];
return ...
}
};
struct factoryB
{
std::map<int, std::shared_ptr<B> > myMap;
factoryB()
{
// setup values to search against
myMap[0] = std::make_shared<B>();
myMap[1] = std::make_shared<derivedB1>();
myMap[2] = std::make_shared<derivedB2>();
//...room for more
}
error_handle_t make_object(int key, std::shared_ptr<B>& object)
{
object = myMap[key];
return ...
}
};
看起来 "interface" 抽象 class 可能是一个合适的基础 class 但每个工厂的 return 类型不同。 class A 和 B 之间没有共同的基数 class 无法像那样工作 "nicely" 所以我做不到
error_handle_t make_object(int key, std::shared_ptr<base_for_A_and_B>& object) = 0;
但是上面的工厂看起来很像样板,几乎可以这样参数化
template <typename T>
struct base
{
std::map<int, std::shared_ptr<T> > myMap;
error_handle_t make_object(int key, std::shared_ptr<T>& object)
{
object = myMap[key];
return ...
}
};
根据 Override template member in Interface,我无法将模板 class 虚拟为抽象 class。
但是如果我们可以假设 make_object 的 "algorithm" 是相同的。我在网上读到这可能是一个实用程序 class 这样
struct factoryA : private base<A>
{
std::map<int, std::shared_ptr<A> > myMap;
error_handle_t make_object(int key, std::shared_ptr<A>& object)
{
...
object = myMap[key];
return ...
}
};
但我并没有覆盖模板库,只是将其用作辅助函数。并没有真正解决我想要实现的目标。
最终目标是拥有一个抽象工厂,这样
struct factories
{
template <typename T>
error_handle_t create(int key, shared_ptr<T>& object)
{
object = make_shared<T>()->make_object(key)
return ...;
}
};
而不是创建没有共同基础的相同对象 class。
struct factories
{
// Initialize in ctor which I didn't include here
factoryA concrete_factoryA;
factoryB concrete_factoryB;
error_handle_t createA(int key, shared_ptr<A>& object)
{
object = concrete_factoryA.make_object(key);
return ...;
}
error_handle_t createB(int key, shared_ptr<B>& object)
{
object = concrete_factoryB.make_object(key);
return ...;
}
};
所以我必须创建一个 create 方法,它包含的工厂数量与它包含的工厂数量一样多,而无需以某种干净的方式利用模板和类型推导。想法或建议?
我想要的用法:
factories l_factories;
shared_ptr<A> a_ptr;
shared_ptr<B> b_ptr;
l_factories.create(0, a_ptr);
l_factories.create(1, b_ptr);
与我拥有的相比:
factories l_factories;
shared_ptr<A> a_ptr;
shared_ptr<B> b_ptr;
l_factories.createA(0, a_ptr);
l_factories.createB(1, b_ptr);
公平地说,我不确定您在寻找什么...这可能应该是评论而不是建议的答案,但这是我所知道的编写格式正确的代码的唯一方法。请原谅我。
这句话让我觉得你正在寻找类似的东西:
template<typename T>
struct factory<T>;
template<>
struct factory<A>
{
std::shared_ptr<A> make_object()
{
// ...
}
};
template<>
struct factory<B>
{
std::shared_ptr<B> make_object()
{
// ...
}
};
听起来好吗?
我无法描述 derived 类.
的作用是什么
你可能想要这样的东西:
template <typename T>
struct factory
{
error_handle_t create(int key, shared_ptr<T>& object)
{
object = make_shared<T>()->make_object(key)
return ...;
}
};
template <typename ... Facts>
struct factories : Facts...
{
using Facts::create...; // C++17, but can be done in C++11 with recursion
};
using factoryA = factory<A>;
using factoryB = factory<B>;
using MyFactory = factories<factoryA, factoryB>;
在 C++11 中,factories
将是:
template <typename ... Facts> // Main declaration
struct factories {}; // Empty case
template <typename Fact>
struct factories<Fact> : Fact{};
template <typename Fact, typename ... Facts>
struct factories<Fact, Facts...> : Fact, factories<Facts...>
{
using Fact::create;
using factories<Facts...>::create;
};
然后
MyFactory l_factories;
shared_ptr<A> a_ptr;
shared_ptr<B> b_ptr;
l_factories.create(0, a_ptr);
l_factories.create(1, b_ptr);
我正在尝试创建一个抽象工厂模式,其中我有两个工厂,我们称它们为 factoryA 和 factoryB。我将使用 struct 而不是 class 来节省一些输入。
对于一些继承的classes家族,让我们从一些class A开始,
struct A
{
// ...
};
struct derivedA1 : public A
{
// ...
};
struct derivedA2 : public derivedA1
{
// ...
};
为了便于说明,现在让我们对其他 class B 做同样的事情。
struct B
{
// ...
};
struct derivedB1 : public B
{
// ...
};
struct derivedB2 : public derivedB1
{
// ...
};
因此,对于这些 classes,我正在尝试创建一个工厂模式(请注意,在我的工作中,我们使用自定义错误处理,我将调用 error_handle_t,其实现无关紧要):
struct factoryA
{
std::map<int, std::shared_ptr<A> > myMap;
factoryA()
{
// setup values to search against
myMap[0] = std::make_shared<A>();
myMap[1] = std::make_shared<derivedA1>();
myMap[2] = std::make_shared<derivedA2>();
//...room for more
}
error_handle_t make_object(int key, std::shared_ptr<A>& object)
{
object = myMap[key];
return ...
}
};
struct factoryB
{
std::map<int, std::shared_ptr<B> > myMap;
factoryB()
{
// setup values to search against
myMap[0] = std::make_shared<B>();
myMap[1] = std::make_shared<derivedB1>();
myMap[2] = std::make_shared<derivedB2>();
//...room for more
}
error_handle_t make_object(int key, std::shared_ptr<B>& object)
{
object = myMap[key];
return ...
}
};
看起来 "interface" 抽象 class 可能是一个合适的基础 class 但每个工厂的 return 类型不同。 class A 和 B 之间没有共同的基数 class 无法像那样工作 "nicely" 所以我做不到
error_handle_t make_object(int key, std::shared_ptr<base_for_A_and_B>& object) = 0;
但是上面的工厂看起来很像样板,几乎可以这样参数化
template <typename T>
struct base
{
std::map<int, std::shared_ptr<T> > myMap;
error_handle_t make_object(int key, std::shared_ptr<T>& object)
{
object = myMap[key];
return ...
}
};
根据 Override template member in Interface,我无法将模板 class 虚拟为抽象 class。
但是如果我们可以假设 make_object 的 "algorithm" 是相同的。我在网上读到这可能是一个实用程序 class 这样
struct factoryA : private base<A>
{
std::map<int, std::shared_ptr<A> > myMap;
error_handle_t make_object(int key, std::shared_ptr<A>& object)
{
...
object = myMap[key];
return ...
}
};
但我并没有覆盖模板库,只是将其用作辅助函数。并没有真正解决我想要实现的目标。
最终目标是拥有一个抽象工厂,这样
struct factories
{
template <typename T>
error_handle_t create(int key, shared_ptr<T>& object)
{
object = make_shared<T>()->make_object(key)
return ...;
}
};
而不是创建没有共同基础的相同对象 class。
struct factories
{
// Initialize in ctor which I didn't include here
factoryA concrete_factoryA;
factoryB concrete_factoryB;
error_handle_t createA(int key, shared_ptr<A>& object)
{
object = concrete_factoryA.make_object(key);
return ...;
}
error_handle_t createB(int key, shared_ptr<B>& object)
{
object = concrete_factoryB.make_object(key);
return ...;
}
};
所以我必须创建一个 create 方法,它包含的工厂数量与它包含的工厂数量一样多,而无需以某种干净的方式利用模板和类型推导。想法或建议?
我想要的用法:
factories l_factories;
shared_ptr<A> a_ptr;
shared_ptr<B> b_ptr;
l_factories.create(0, a_ptr);
l_factories.create(1, b_ptr);
与我拥有的相比:
factories l_factories;
shared_ptr<A> a_ptr;
shared_ptr<B> b_ptr;
l_factories.createA(0, a_ptr);
l_factories.createB(1, b_ptr);
公平地说,我不确定您在寻找什么...这可能应该是评论而不是建议的答案,但这是我所知道的编写格式正确的代码的唯一方法。请原谅我。
这句话让我觉得你正在寻找类似的东西:
template<typename T>
struct factory<T>;
template<>
struct factory<A>
{
std::shared_ptr<A> make_object()
{
// ...
}
};
template<>
struct factory<B>
{
std::shared_ptr<B> make_object()
{
// ...
}
};
听起来好吗? 我无法描述 derived 类.
的作用是什么你可能想要这样的东西:
template <typename T>
struct factory
{
error_handle_t create(int key, shared_ptr<T>& object)
{
object = make_shared<T>()->make_object(key)
return ...;
}
};
template <typename ... Facts>
struct factories : Facts...
{
using Facts::create...; // C++17, but can be done in C++11 with recursion
};
using factoryA = factory<A>;
using factoryB = factory<B>;
using MyFactory = factories<factoryA, factoryB>;
在 C++11 中,factories
将是:
template <typename ... Facts> // Main declaration
struct factories {}; // Empty case
template <typename Fact>
struct factories<Fact> : Fact{};
template <typename Fact, typename ... Facts>
struct factories<Fact, Facts...> : Fact, factories<Facts...>
{
using Fact::create;
using factories<Facts...>::create;
};
然后
MyFactory l_factories;
shared_ptr<A> a_ptr;
shared_ptr<B> b_ptr;
l_factories.create(0, a_ptr);
l_factories.create(1, b_ptr);