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

Dan*_*iel 4 c++ design-patterns strategy-pattern c++11

给定典型的策略模式

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

对我来说,在这种设计中,尚不清楚是否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
}
Run Code Online (Sandbox Code Playgroud)

鉴于安全指针,现在是否应该最好注入安全指针并拥有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_;
}
Run Code Online (Sandbox Code Playgroud)

或者是否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_;
}
Run Code Online (Sandbox Code Playgroud)

这种设计当然会引入其自身的问题,特别是只能将动态分配Strategy的注入Context

Mic*_*CMS 5

设计取决于实施者。

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

要直接回答您的问题:

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

为了进一步回答这个问题:

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

原因是,智能指针实际上是根据内存所有权策略进行自我记录的,因此您可以摆脱“如果没有良好的记录”的缺点。

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

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

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

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


Pup*_*ppy 3

你这样做是错的。

鉴于std::function,您刚刚编写的所有内容都完全过时了,您应该只使用std::function<int()>一些 lambda。

  • 虽然我很欣赏您的意见,但如果您能解释为什么使用“std::function”是一种更好的方法,而不是仅仅斥责我的问题,那就太好了。 (5认同)