设计算法的通用选项

时间:2009-03-02 12:17:54

标签: c++ design-patterns

我想知道是否有用于为一组算法指定选项的设计模式。我正在使用C ++。 让我来描述我的问题。我有一套算法,这些算法有不同的选择。我想设计一个单点访问这些算法。类似于策略模式的东西。此单点访问是一个控制器类,它将输入作为通用选项类。根据选项,将使用合适的算法。我想概括这些选项,以便我可以扩展算法和客户端。 谢谢, AMOL

3 个答案:

答案 0 :(得分:7)

经常使用的模式是创建一个策略类,它作为模板类型传递给您的类,然后从私有继承:

template <typename Policy>
class fancy_algorithm : private Policy {
};

一个着名的例子是std::allocator类,它通常以这种方式继承:

template <typename T, typename Alloc = std::allocator<T> >
class my_container : private Alloc {
public:
    typedef Alloc allocator;

    // It's necessary to make the base class names available explicitly.
    typedef typename allocator::pointer pointer;

    using allocator::construct;
    // …
};

答案 1 :(得分:3)

我同意康拉德的政策性设计。我还建议Modern C++ Design: Generic Programming and Design Patterns Applied。在本书之后,你对C ++的看法将永远改变;)

答案 2 :(得分:2)

Konrad's suggestion of using policy types上构建,如果您的算法在构造时需要参数,则可以通过要求任何Policy类具有名为Params的嵌套类型来干净地处理此问题,然后提供fancy_algorithm<Policy>内的构造函数,它接受此类型的参数并将其传递给包含的Policy对象:

template <typename Policy>
class fancy_algorithm : private Policy {
public:
    typedef typename Policy::Params Params;    // Need to redeclare :(

    explicit fancy_algorithm(Params params = Params()) : Policy(params) {}
};

任何相关参数都需要打包到Policy::Params类型的单个对象中。

Policy类始终使用类型Policy::Params的单个参数构造。要使用(可能)不需要参数的策略类,请在Params中提供默认构造函数(或使用隐式声明的构造函数),而不是Policy。这样,通过使用上面fancy_algorithm<Policy>构造函数的默认值,只要fancy_algorithm<Policy>具有默认构造函数(即Policy::Params时,我们就会启用Policy的方便的默认构造}不需要任何参数)。没有安全性丢失:如果Policy::Params缺少默认构造函数(表示某些参数 required ),则任何默认构造fancy_algorithm<Policy>对象的尝试都将在编译时失败。

示例:

struct multiply_by_params {
    multiply_by_params(int x /* = 42 */) : _x(x) {}     // See bottom
    int get() const { return _x; }    // Or, just make multiply_by a friend

private:
    int _x;
};

struct multiply_by {
    typedef multiply_by_params Params;
    multiply_by(Params p) : _x(p.get()) { /* Other initialisation */ }

    // Other code implementing the strategy (e.g. an operator()())
    ...

private:
    int _x;
};

fancy_algorithm<multiply_by> a(69); // Always compiles
fancy_algorithm<multiply_by> b;     // Compiles iff /* = 42 */ is uncommented