应该在策略模式中使用安全指针吗?

时间:2015-02-06 11:24:23

标签: c++ c++11 design-patterns strategy-pattern

给出典型的策略模式

class Strategy
{
public:
    virtual int execute() const = 0;
}

class StrategyA : public Strategy
{
public:
    int execute() const override;
}

class StrategyB : public Strategy
{
public:
    int execute() const override;
}

我相信实现上下文类的'pre-C ++ 11'方式类似于

class ContextRaw
{
public:
    ContextRaw(Strategy* the_strategy);
    ~ContextRaw(); // Should this delete the_strategy_?
    int execute() const;
private:
    Strategy* the_strategy_;
}

对我来说,在这个设计中,不清楚Context是否应该对Strategy负责,除非有明确的文件说明否则,否则可能会发生坏事

void trouble()
{
    StrategyA a_concrete_strategy;
    ContextRaw a_context(&a_concrete_strategy); // Oops, Context may try to delete stack variable
}

void more_trouble()
{
    Strategy* a_concrete_strategy = new StrategyA;
    ContextRaw* a_context       = new ContextRaw(a_concrete_strategy);
    ContextRaw* another_context = new ContextRaw(a_concrete_strategy);
    delete a_context;
    std::cout << another_context.execute() << std::endl; // Oops, the_strategy is deleted
}

根据安全指针,现在最好是注入安全指针,让Context取得Strategy的所有权吗?

class ContextUnique
{
public:
    ContextUnique() = delete;
    ContextUnique(std::unique_ptr<Strategy> the_strategy);
    ~ContextUnique();
    int execute() const;
private:
    std::unique_ptr<Strategy> the_strategy_;
}

Strategy是否可以在不同的Context之间共享?

class ContextShared
{
public:
    ContextShared() = delete;
    ContextShared(std::shared_ptr<Strategy> the_strategy);
    ~ContextShared();
    int execute() const;
private:
    std::shared_ptr<Strategy> the_strategy_;
}

这个设计当然会引入它自己的问题,特别是只有动态分配的Strategy可以注入Context

3 个答案:

答案 0 :(得分:5)

设计取决于实施者。

请注意,在您的示例中,您引用了使用非C ++ 11指针搞乱策略模式的不同方法。

直接回答您的问题:

是的,您应该在策略模式中使用智能指针。

进一步回答这个问题:

你应该尽可能使用智能指针。

原因是智能指针实际上就内存所有权政策而言是自我记录的,所以你摆脱了“如果没有好文档”的一些缺点。

考虑您为Context类公开的原型,您可以告诉用户您的期望是什么:

    如果您希望用户将内存所有权传递给您,则
  • unique_ptr
  • shared_ptr如果您希望在多个所有者上使用相同的策略实施
  • weak_ptr如果您希望用户处理内存管理

什么是更安全,取决于你。但是,您可以告诉用户上下文可以与其他上下文共享它的具体策略,或者每个上下文有1个具体策略。

作为一种设计方法,我建议使用1策略/上下文(so unique_ptr),因为您的具体策略最终可能会有一些内部变量是唯一的/上下文,并且事情会变得复杂起来。

答案 1 :(得分:2)

你做错了。

根据std::function,您刚写完的所有内容都已完全过时,您只需使用std::function<int()>和一些lambdas。

答案 2 :(得分:0)

它在很大程度上取决于Strategy对象的真正目的是它们是应该在各种Context对象之间共享还是由它们拥有。

至少在您使用共享或独特的ptr时,您可以清楚地定义您的意图。只有当你要“查看”其他一些对象时,你才应该使用“原始”指针(你不共享或拥有它 - 你确定指向对象不会比指向对象更长)。