如何与战略设计模式互动

时间:2014-01-09 15:26:23

标签: c++ design-patterns

我想问一些关于设计模式的问题。 让我们以战略设计模式为例:

class Printer{
public:
   void print(Message){

   }
};

class Message{
public:
   void print();
};

class SingleMessage : public Message{
   string s;
public:
   void print();
};

class Messages : public Message{
   vector<Message> v;
public:
   void print();
};

根据这种模式的UML,打印机应该有方法打印(Message)。我不明白(对不起,如果这是愚蠢的问题)是我们需要调用Message类打印方法还是什么?我们需要打印出消息,但我们不能在类Printer中创建新的Message对象,因为那时它将是合成。那么我们该怎么做呢?

另外,也许您可​​以分享一些教程,其中将解释设计模式(如何使用它们,何时使用它们等)?

3 个答案:

答案 0 :(得分:4)

首先,组合的概念与设计模式完全不同。大多数设计模式使用组合 - 这完全没问题。

其次,不,你不在这里使用作文。您调用传递给打印机的参数的print函数:

class Printer{
public:
    void print(Message& m) {
        m.print();
    }
};

我已经完成并修复了一个错误:参数需要通过引用传递(或作为指针),否则会丢失动态类型。因此,Message::print函数也需要声明为virtual

答案 1 :(得分:1)

您可能想要做的是提供Printer作为策略。您可以对CoutPrinter FilePrinterPrinterPrinter ...

进行说明
class Printer{
public:
   virtual void print(const string& message) = 0;
};

class CoutPrinter{
public:
   void print(const string& message) override {
        std::cout << message << "\n";
   }
};

然后,您可以使用此概念打印消息:

class Message{
public:
   virtual print(Printer& printer) = 0;
};

class SingleMessage : public Message {
   string s;
public:
   void print(Printer& printer) override
   {
      printer.print(s)
   }
};

class Messages {
   vector<Message> messages;
   std::unique_ptr<Printer> printer;

public:

    /// Inject the concrete Printer strategy here
    Messages(std::unique_ptr<Printer> printerStrategy) : 
      printer(move(printer))
    {}

    void print() {
       for(auto& m : messages)
        m.print(*printer);
   }
};

您可以知道使用构造函数注入为消息选择不同的打印机

int main()
{
    Messages messages {std::make_unique<CoutPrinter>()};
    messages.print();  // will print all messages to std::cout
}

复合图案

在您的示例中,您从Message发送了消息。这是复合模式。你可以把两者结合起来:

class Messages : public Messages {
   vector<Message> messages;
public:
    void print(Printer& printer) override {
       for(auto& m : messages)
         m.print(*printer);
   }
};

int main()
{
    Messages messages;
    CoutPrinter printer;
    messages.print(printer);  // will print all messages to std::cout
}

答案 2 :(得分:1)

  

我不明白(对不起,如果这是愚蠢的问题)我们需要调用Message类打印方法还是什么?

是。 Message :: print函数应该是抽象的,并且在继承自Message的每个类中实现(作为不同的策略)。

  

我们需要打印出消息,但我们不能在类Printer中创建新的Message对象,因为那时它将是合成。那么我们该怎么做呢?

您无需在打印机中创建新实例(即此处不需要合成)。您在此处所做的就是通过决定将哪些具体实现传递到Printer :: print函数来选择打印的实现策略。

  

另外,也许您可​​以分享一些教程,其中将解释设计模式(如何使用它们,何时使用它们等)?

通常,设计模式是重现设计问题的惯用解决方案。您可以在维基百科上找到有关何时使用它们的详细信息。例如,this page说:

  

“在计算机编程中,策略模式(也称为   策略模式)是一种软件设计模式,即算法的模式   可以在运行时选择行为。“

作为旁注,这不是战略模式的一个很好的例子。一个更好的方法就是抽象印刷意味着什么,而不是消息意味着什么:

class Message{
public:
    void display(Printer& p) {
        p.print(*this); // what printing strategy is applied to
                        // display the message depends on the
                        // concrete type of the parameter (on what 
                        // Printer specialization you call
                        // the function with)
    }
};

struct Printer{
   virtual void print(Message& m);
};

struct BWPrinter: Printer {
     virtual void print(Message& m);
};

struct ColorPrinter: Printer {
     virtual void print(Message& m);
};

struct IOStreamPrinter: Printer {
    IOStreamPrinter(std::iostream& s);
    virtual void print(Message& m);
};