有人可以向我解释模板方法模式和策略模式之间的区别是什么?
据我所知,它们是99%相同 - 唯一的区别是模板方法模式有一个抽象类作为基类,而策略类使用由每个具体策略类实现的接口.
但是,就客户而言,它们的使用方式完全相同 - 这是正确的吗?
当特定操作具有可以根据其他变化的原始行为定义的一些不变行为时,使用模板模式.抽象类定义了不变行为,而实现类定义了依赖方法.
在策略中,行为实现是独立的 - 每个实现类定义行为,并且它们之间没有共享代码.两者都是行为模式,因此,客户以相同的方式消费.通常,策略具有单个公共方法 - execute()
方法,而模板可以定义一组公共方法以及子类必须实现的一组支持私有原语.
这两种模式可以很容易地一起使用.您可能有一个策略模式,其中多个实现属于使用模板模式实现的一系列策略.
两者之间的主要区别在于选择具体算法时.
使用Template方法模式,这可以在编译时通过继承模板来实现.每个子类通过实现模板的抽象方法提供不同的具体算法.当客户端调用模板外部接口的方法时,模板会根据需要调用其抽象方法(其内部接口)来调用算法.
class ConcreteAlgorithm : AbstractTemplate { void DoAlgorithm(int datum) {...} } class AbstractTemplate { void run(int datum) { DoAlgorithm(datum); } virtual void DoAlgorithm() = 0; // abstract }
相反,策略模式允许在运行时通过包含来选择算法.具体算法由单独的类或函数实现,这些类或函数作为其构造函数或setter方法的参数传递给策略.为此参数选择的算法可以根据程序的状态或输入动态变化.
class ConcreteAlgorithm : IAlgorithm { void DoAlgorithm(int datum) {...} } class Strategy { Strategy(IAlgorithm algo) {...} void run(int datum) { this->algo.DoAlgorithm(datum); } }
模板方法模式:通过子类化选择编译时算法
策略模式:通过包含选择运行时算法
我认为两种模式的类图都显示出差异.
策略
封装类中的算法
链接到图像
模板方法
将算法的确切步骤推迟到子类
链接到图像
您可能意味着模板方法模式.你是对的,他们提供非常相似的需求.我想说,如果你有一个"模板"算法有定义的步骤,其中子类覆盖这些步骤来改变一些细节,那么最好使用模板方法.在策略的情况下,您需要创建一个接口,而不是继承您使用委托.我会说它是一个更强大的模式,也许更好根据DIP - 依赖倒置原则.它更强大,因为你清楚地定义了一个新的策略抽象 - 一种做某事的方法,它不适用于模板方法.所以,如果这种抽象有意义 - 使用它.但是,使用模板方法可以在简单的情况下为您提供更简单的设计,这也很重要.考虑哪些词更适合:你有模板算法吗?或者在这里关键是你有一个战略抽象 - 做某事的新方法
模板方法示例:
Application.main() { Init(); Run(); Done(); }
在这里,您从应用程序继承并替换将在init,run和done上完成的操作.
策略示例:
array.sort (IComparercomparer)
在这里,编写比较器时,不会从数组继承.Array将比较算法委托给比较器.
策略和模板方法模式之间有很多相似之处.策略和模板方法模式都可用于满足开放 - 封闭原则,并使软件模块易于扩展而无需更改其代码.两种模式都表示通用功能与该功能的详细实现的分离.但是,它们提供的粒度方面略有不同.
以下是我在研究这两种模式时观察到的一些差异:
在策略中,客户端和策略之间的耦合更加松散,而在模板方法中,两个模块的耦合更紧密.
在策略中,大多使用接口虽然也可以根据情况使用抽象类,但不使用具体类,而在Template方法中大多使用抽象类或具体类,不使用接口.
在策略模式中,通常用接口表示类的整个行为,另一方面,模板方法用于减少代码重复,样板代码在基础框架或抽象类中定义.在Template Method中,甚至可以有一个具有默认实现的具体类.
简单来说,您可以在策略模式中更改整个策略(算法),但是,在模板方法中,只有一些事情发生变化(算法的一部分),其余部分保持不变.在模板方法中,不变步骤在抽象基类中实现,而变体步骤要么是默认实现,要么根本没有实现.在Template方法中,组件设计者强制要求算法的所需步骤和步骤的顺序,但允许组件客户端扩展或替换一些这些步骤.
图片取自bitesized博客.
继承与聚合(is-a与has-a).这是实现同一目标的两种方式.
这个问题显示了选择之间的一些权衡:继承与聚合
两者都非常相似,并且两者都以类似的方式被客户端代码使用.与上面最流行的答案不同,两者都允许在运行时选择算法.
两者之间的区别在于,虽然策略模式允许不同的实现使用完全不同的方式来实现期望的结果,但模板方法模式指定了用于实现结果的总体算法("模板"方法) - - 留给特定实现(子类)的唯一选择是所述模板方法的某些细节.这是通过让模板方法对一个或多个被子类重写(即实现)的抽象方法进行调用来完成的,这与模板方法不同,模板方法本身不是抽象的,也没有被子类覆盖.
客户端代码使用抽象类类型的引用/指针调用模板方法,该引用/指针指向可以在运行时确定的具体子类之一的实例,就像使用策略模式时一样.
模板方法:
它基于继承
定义不能由子类更改的算法框架.只能在子类中覆盖某些操作
父类完全控制算法,并且仅将某些步骤与具体类区分开来
绑定在编译时完成
Template_method结构:
战略:
它基于委托/组成
它通过修改方法行为来改变对象的内容
它用于在算法族之间切换
它通过在运行时用其他算法完全替换一个算法来改变运行时对象的行为
绑定在运行时完成
战略结构:
看看模板方法和策略文章,以便更好地理解.
相关文章:
JDK中的模板设计模式无法找到定义要按顺序执行的方法集的方法
战略模式的现实世界范例