使用类似的工厂类删除重复代码

Remove duplicate code with similar factory classes

本文关键字:删除 代码 工厂      更新时间:2023-10-16

我有此代码:

struct Foo1 {}
struct Foo1Helper {} // generated
struct Foo2 {}
struct Foo2Helper {} // generated
struct Foo1Factory {
    Foo1* Create(){
        return connect();
    }
protected:
    Foo1 *connect();
}
// cpp file (important because i don't want to have Foo1Helper in .h file)
Foo1* Foo1Factory::connect(){
    return Foo1Helper::doSmth();
}
struct Foo2Factory {
    Foo2* Create(){
        return connect();
    }
protected:
    Foo2 *connect();
}
// cpp file (important because i don't want to have Foo2Helper in .h file)
Foo2* Foo2Factory::connect(){
    return Foo2Helper::doSmth();
}

我有两个类foo1和foo2,两者都是在Foo1helper和Foo2Helper类的帮助下创建出工厂类的。

这个想法是某种程度上只有一个工厂类,因为有很多重复的代码,唯一的区别是连接函数中称为的辅助函数。

注意:我想从标题文件中隐藏助手类,以便必须在.cpp文件中实现连接函数。

如果您可以定义一些别名,则可以拥有一个工厂,如果您可以使用一些明确的模板实例化,则可以将助手类隐藏在CPP中。而且我不明白你为什么不会。

在以下我的假设中,您的工厂方法是静态的。如果不是,则可以很容易地使用pimpl习惯。

标题文件

struct Foo1 { /* implementation */  };
struct Foo1Helper; // just declaration
struct Foo2 { /* implementation */ };
struct Foo2Helper; // just declaration
// a little helper
template <class Foo_main, class Helper>
struct Foo_trait
{
    using Foo = Foo_main;
    using FooHelper = Helper;
};

// this section can be easily generated
// if you have a lot of classes and feel particularly lazy
using Foo1_trait = Foo_trait<Foo1, Foo1Helper>;
using Foo2_trait = Foo_trait<Foo2, Foo2Helper>;

// just one Factory class
// no implementation exposed to the header
template <class Foo_trait>
struct FooFactory
{
    using Foo = typename Foo_trait::Foo;
    using FooHelper = typename Foo_trait::FooHelper;
    static auto Create() -> Foo*;
};

源文件

struct Foo1Helper
{
    static Foo1* doSmth()
    {
        static Foo1 f;
        return &f;
    }
};
struct Foo2Helper
{
    static Foo2* doSmth()
    {
        static Foo2 f;
        return &f;
    }
};

template <class Foo_trait>
auto FooFactory<Foo_trait>::Create() -> Foo*
{
    return FooHelper::doSmth();
}
// explicit template instantiation
// very important. Without this you get linker erorrs
// again very easy to generate
template struct FooFactory<Foo1_trait>;
template struct FooFactory<Foo2_trait>;

用法

Foo1 f1 = FooFactory<Foo1_trait>::Create();
Foo2 f2 = FooFactory<Foo2_trait>::Create();

如果您控制了FooN,则可以完全跳过Foo_trait并定义FooN内的别名。例如

struct Foo1
{
    using Helper = Foo1Helper;
};