2010-04-04 55 views
3

我还没有阅读Modern C++ Design书,但已经发现通过模板感兴趣的行为注入的想法。我现在正在尝试自己应用它。应用基于策略的设计问题

我有一个类,有一个记录器,我认为可以作为一个政策注入。该记录器有一个log()方法这需要根据其政策的一个的std :: string或std :: wstring的:

// basic_logger.hpp 
template<class String> 
class basic_logger 
{ 
public: 
    typedef String string_type; 

    void log(const string_type & s) { ... } 
}; 
typedef basic_logger<std::string> logger; 
typedef basic_logger<std::wstring> wlogger; 

// reader.hpp 
template<class Logger = logger> 
class reader 
{ 
public: 
    typedef Logger logger_type; 

    void read() 
    { 
     _logger.log("Reading..."); 
    } 

private: 
    logger_type _logger; 
}; 

现在的追问是,如果读者需要记录仪作为一个参数,像上面,或者如果它需要一个字符串,然后实例化一个basic_logger作为一个实例变量?像这样:

template<class String> 
class reader 
{ 
public: 
    typedef String string_type; 
    typedef basic_logger<string_type> logger_type; 

    // ... 

private: 
    logger_type _logger; 
}; 

什么是正确的路要走?

+1

请注意,更少的注入东西 - 这是C++。 – 2010-04-04 20:15:49

+0

我知道我有点受到Java损坏(我主要与它合作,但我不是它的粉丝)。行为和状态仍然需要以某种方式注入(或者任何你想要调用它的),它是C++,Ruby还是其他。有了C++,从我从Boost中了解到的情况来看,基于策略的设计就是最好的选择。我只是想把头围住它。 – Arthur 2010-04-04 20:24:49

+1

实际上阅读现代C++设计可能会帮助你最好的,因为Alexandrescu显示类似的例子。 – 2010-04-04 20:25:57

回答

2

要实际使用策略类,策略需要是模板参数。一个例子是basic_string的char_traits参数,尽管它的实现方式与MC++ D的策略不同,后者使用继承来利用空的基类优化,并允许轻松地添加到类的公共接口(以一种更好的方式包装每种可能的方法;再次,读MC++ D)。您仍然可以提供默认值:

template<class String, class Logger=basic_logger<String> > 
struct reader : Logger { 
    void read() { 
    this->log("Reading..."); 
    } 
}; 
+0

我想你是对的,你说我应该阅读Alexandrescu的书。我从书中找到了一些例子,但是如果没有这本书,将例子放到上下文中会有点困难。例如,我不知道空基类优化。 无论如何,我想这回答了我的问题。谢谢! – Arthur 2010-04-05 09:22:16

1

问题应该由读者根据其记录器的类型或其读取的类型进行参数化?如果这是问题,我会认为答案很明显 - 后者。

这个问题恕我直言,恕我直言,既没有字符串也没有记录器实际上是政策。一个策略在编译时说,记录器应该如何去记录日志 - 你的代码只是向读者提供一种记录器,这在使用继承的时候也可以在运行时完成。

+0

你说得对。在这种情况下,记录器最好在运行时设置。但是,如果你认为记录器是一种记录策略,我认为罗杰在上面回答了我的问题。 正如我之前所说,我仍然试图围绕政策... – Arthur 2010-04-05 09:29:04

1

策略通常是影响类行为的参数。

从课堂上提取策略是非常困难的,更困难的一点是策略需要覆盖正交概念,以便您可以在不影响其他策略的情况下进行更改......这非常具有挑战性,您可以想象得到。

如果您想查看策略使用的一个很好的示例,请查阅Loki::Singleton,这在书中完全展示。

template 
< 
    typename T, 
    template <class> class CreationPolicy = CreateUsingNew, 
    template <class> class LifetimePolicy = DefaultLifetime, 
    template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL, 
    class MutexPolicy = LOKI_DEFAULT_MUTEX 
> 
class SingletonHolder; 

令人印象深刻,不是吗?

基于策略的设计的原则是,你试着分解你的类的各种动作,以便你可以独立推理它们。

好了,现在我必须承认,我不要求类的模板参数集数的想法很舒适,我个人会者优先的东西一起:

template 
< 
    class T, 
    class CreationPolicy = CreateUsingNew<T>, 
    class LifetimePolicy = DefaultLifeTime<T>, 
    class MutexPolicy = LOKI_DEFAULT_MUTEX, 
    template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL 
> 
class SingletonHolder; 

最后能不能真正得到帮助,你应该通过它自己的SingletonHolder类。

但是我觉得它更容易在这里互换政策,它可以让我像定义策略:

template <class T, size_t Param> MyCreationPolicy; 

并直接使用,而无需使其签名匹配,它包起来PARAM的给定值。

+0

感谢您的澄清!很有帮助! – Arthur 2010-04-06 13:07:50