我一直在阅读 Gamma 等人写的《设计模式》。我有一个关于模板方法与依赖注入相比的问题。
使用模板方法,您可以使用为所需操作或计算提供替代方案的策略来“模板化”类。因此,您不需要从多种替代方案中选择一种策略并将该策略编码到类中,而是允许类的用户指定他们想要使用的替代方案。
这一切对我来说听起来都很合理。但我在概念上遇到了一些障碍。
如果用策略对象实例化一个类,则该策略对象需要实现一个抽象接口。然后,程序员可以编写不同的策略,这些策略都可以毫无错误地编译到类中,因为这些策略实现了接口。使用策略的类被编码到策略接口而不是实现。
如果你要定义一个摘要IPolicy
对于这些策略对象,为什么不直接使用依赖注入并传入IPolicy
关于施工?
谁能解释一下为什么您更喜欢模板方法而不是依赖注入?
关于“模板方法”(而不是设计模式),以下示例可能有助于了解决定要做什么的优缺点。该示例是创建一个旨在帮助调试/开发的详细模式的库。
带模板
struct console_print
{
static void print(const string& msg) {std::cout<<msg;}
};
struct dont_print
{
static void print(const string& msg) {}
};
template<printer>
void some_function()
{
printer::print("some_function called\n");
}
然后库用户可以编写:
some_function<console_print>(); //print the verbose message;
some_function<dont_print>(); //don't print any messages.
此代码的好处是,如果用户不希望打印代码,则调用dont_print::print(msg)
完全从代码中消失(空静态类很容易被优化掉)。这样的调试消息甚至可以输入到性能关键区域。
模板的缺点是您需要在编译之前决定您的策略。您还需要更改模板的函数/类签名。
没有模板
当然,上面的内容可以通过以下方式完成:
struct printer
{
virtual void print(const std::string& msg) = 0;
}
struct console_print : public printer
{
void print(const std::string& msg) {std::cout<<msg;}
}
struct debug_print : public printer
{
void print(const std::string& msg) {}
}
这样做的优点是您可以将打印机类型传递给您的类和函数,并在运行时更改它们(对于某些应用程序可能非常有用)。然而,代价是总是对虚函数进行调用,因此空的 dont_print 确实有很小的代价。对于性能关键区域来说,这可能是可接受的,也可能是不可接受的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)