【问题标题】:Remove duplicate code with similar factory classes删除具有相似工厂类的重复代码
【发布时间】:2017-08-31 21:02:42
【问题描述】:

我有这个代码:

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 类的帮助下使用工厂类创建的。

这个想法是因为有很多重复的代码,所以只有一个工厂类,唯一的区别是在连接函数中调用的辅助函数。

注意:我想从头文件中隐藏 Helper 类,因此连接功能必须在 .cpp 文件中实现。

【问题讨论】:

  • 问题是什么?这段代码有太多错误,对我来说没有任何意义
  • 这个问题比its predecessor 更有意义,但仍然是一头雾水。您有两个工厂,每个工厂都将对象创建指向不同的帮助类,每个都动态生成不同的对象类型。我想你可以在某处堵塞模板专业化或一些函数重载,但实际的最终目标仍然不完全清楚。 Foo1HelperFoo2Helper 迟早要被明确使用。

标签: c++ templates factory


【解决方案1】:

如果你能忍受定义一些别名,你可以拥有一个工厂,如果你能忍受一些显式的模板实例化,你可以在 cpp 中隐藏你的 Helper 类。我不明白你为什么不这样做。

在下面我假设您的工厂方法是静态的。如果不是,它可以很容易地用 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;
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-12
    相关资源
    最近更新 更多