我一直在阅读 Gamma 等人的《设计模式》。与依赖注入(inject)相比,我有一个关于模板方法的问题。
使用模板方法,您可以使用为所需操作或计算提供备选方案的策略“模板化”类。因此,与其从多个备选方案中选择一个策略并将该策略编码到类中,不如让类的用户指定他们想要使用的备选方案。
我觉得这一切都非常合理。但我遇到了一点概念上的障碍。
如果用策略对象实例化一个类,策略对象需要实现一个抽象接口(interface)。然后程序员可以编写不同的策略,所有策略都可以无误地编译到类中,因为策略实现了接口(interface)。使用策略的类被编码到策略接口(interface)而不是实现。
如果您要为这些策略对象定义一个抽象的 IPolicy
,为什么不直接使用依赖注入(inject)并在构造时传入 IPolicy
?
谁能阐明为什么您更喜欢模板方法而不是依赖注入(inject)?
最佳答案
关于“模板方法”(而不是设计模式),以下示例可能有助于确定要做什么的利弊。该示例是创建旨在帮助调试/开发的库的详细模式。
使用模板
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 确实有很小的代价。对于性能关键区域,这可能是可接受的,也可能是 Not Acceptable 。
关于c++ - 为什么更喜欢模板方法而不是依赖注入(inject)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8134436/