多态工厂

Polymorphic factory

本文关键字:工厂 多态      更新时间:2023-10-16

考虑以下代码:

template <typename T>
class DrawerFactory
{
protected:
    DrawerFactory() {};
private:
    virtual shared_ptr<IDrawer> GetDrawer(T settings) = 0;
};
class ConcreteDrawerFactoryA : public DrawerFactory<SettingsA>
{
public:
    shared_ptr<IDrawer> GetDrawer(SettingsA settingsA) override
    {
        if (settingsA.style == A) return make_shared<ConcreteDrawerA>(settingsA.length, settingsA.stroke, settingsA.opacity);
        else return make_shared<ConcreteDrawerB>(20, .5);
    };
};
class ConcreteDrawerFactoryB : public DrawerFactory<SettingsB>
{
public:
    shared_ptr<IDrawer> GetDrawer(SettingsB settingsB) override
    {
        if (settingsB.type == TYPEC) return make_shared<ConcreteDrawerC>(settingsB.width, settingsB.height);
        else return make_shared<ConcreteDrawerD>(10, 2);
    };
};

我可以通过:

获得一个抽屉
ConcreteDrawerFactoryA().GetDrawer(settingsa);

ConcreteDrawerFactoryB().GetDrawer(settingsb);

我想做的是:

DrawerFactory().GetDrawer(settingsa);
DrawerFactory().GetDrawer(settingsb);

是否有一种方法可以设置此问题,而无需不必为我要添加的每个混凝土工厂不断将过载添加到DrawerFactory吗?

而不是工厂层次结构和虚拟调度,您可以使用模板和专业化:

#include <memory>
struct IDrawer { };
struct Drawer1: IDrawer { };
struct Drawer2: IDrawer { };
struct Drawer3: IDrawer { };
struct Drawer4: IDrawer { };
template <class T>
struct DrawerGetterImpl;
struct DrawerFactory {
    template <class T>
    std::shared_ptr<IDrawer> GetDrawer(T settings) {
        return DrawerGetterImpl<T>::GetDrawer(settings);
    }
};
struct SettingsA { int style; };
template <>
struct DrawerGetterImpl<SettingsA> {
    static std::shared_ptr<IDrawer> GetDrawer(SettingsA settings) {
        if (settings.style == 1) {
            return std::make_shared<Drawer1>();
        }
        return std::make_shared<Drawer2>();
    }
};
struct SettingsB { int type; };
template <>
struct DrawerGetterImpl<SettingsB> {
    static std::shared_ptr<IDrawer> GetDrawer(SettingsB settings) {
        if (settings.type == 1) {
            return std::make_shared<Drawer3>();
        }
        return std::make_shared<Drawer4>();
    }
};
int main() {
    DrawerFactory().GetDrawer(SettingsA{1});
}

[live demo]

在您的示例中,您的工厂似乎没有状态,那么如果没有多态工厂,您可以实现想要的目标吗?例如这样的东西...

template<class T>
std::shared_ptr<IDrawer> MakeDrawer(T settings);
template<>
std::shared_ptr<IDrawer> MakeDrawer<SettingsA>(SettingsA settings)
{
    return std::make_shared<ConcreteDrawerA>(); // use settings really
}
template<>
std::shared_ptr<IDrawer> MakeDrawer<SettingsB>(SettingsB settings)
{
    return std::make_shared<ConcreteDrawerB>(); //use settings here
}

void main()
{
   SettingsA setA;
   std::shared_ptr<IDrawer> pA = MakeDrawer(setA);
   SettingsB setB;
   std::shared_ptr<IDrawer> pB = MakeDrawer(setB);
}

您可以使用过载代替模板。