删除具有类似工厂类的重复代码

时间:2017-08-31 21:02:42

标签: c++ templates factory

我有这段代码:

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

这个想法是以某种方式只有一个Factory类,因为有很多重复的代码,唯一的区别是在connect函数中调用的辅助函数。

注意:我想隐藏头文件中的Helper类,因此必须在.cpp文件中实现connect函数。

1 个答案:

答案 0 :(得分:1)

如果您可以使用定义一些别名,则可以拥有一个工厂,如果您可以使用某些显式模板实例,则可以在cpp中隐藏您的Helper类。我不明白为什么你不会。

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

头文件

b.js:4
a.foo();
  ^

TypeError: a.foo is not a function
    at Object.<anonymous> (/Users/dlumma/dev/bloomguild-applitools-sunbasket/scenarios/b.js:4:3)
    at Module._compile (module.js:573:30)
    at Object.Module._extensions..js (module.js:584:10)
    at Module.load (module.js:507:32)
    at tryModuleLoad (module.js:470:12)
    at Function.Module._load (module.js:462:3)
    at Function.Module.runMain (module.js:609:10)
    at startup (bootstrap_node.js:158:16)
    at bootstrap_node.js:598:3

源文件

var my = d3.select('#my');

var dataSet = [
  [{firstName:'John', lastName:'Doe'},{firstName:'Jane',lastName:'Doe'}],
  [{firstName:'Henry',lastName:'Smith'},{firstName:'Jane',lastName:'Smith'}],
  [{firstName:'Fred',lastName:'Fox'}]
];

var rows = my.selectAll('div')
    .data(dataSet)
    .enter()
    .append('div');

var col = rows.selectAll('span').data(function(d,i){
  return d;
},function(d,i){
 return d.lastName+d.firstName;
});

col.enter().append('span').html(
function(d,i){return '&bull; '+ d.firstName + ' '+ d.lastName+' ';}
);

使用

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内定义别名。 E.g。

Foo_trait