谁能给我解释一下模板方法模式和策略模式的区别是什么?
据我所知,它们99%是一样的——唯一的区别是 模板方法模式有一个抽象类作为基础 类,而策略类使用已实现的接口 由每个具体的策略类。
然而,就客户端而言,它们是以完全相同的方式被消费的——这是正确的吗?
谁能给我解释一下模板方法模式和策略模式的区别是什么?
据我所知,它们99%是一样的——唯一的区别是 模板方法模式有一个抽象类作为基础 类,而策略类使用已实现的接口 由每个具体的策略类。
然而,就客户端而言,它们是以完全相同的方式被消费的——这是正确的吗?
当前回答
模板方法:
它是基于继承的 定义了不能被子类改变的算法框架。只有某些操作可以在子类中被重写 父类完全控制算法,只与具体类的某些步骤不同 绑定在编译时完成
Template_method结构:
策略:
它基于委托/组合 它通过修改方法行为来改变对象的内容 它用来在一系列算法之间切换 它通过在运行时完全将一种算法替换为另一种算法来改变对象在运行时的行为 绑定在运行时完成
战略结构:
为了更好地理解,请查看Template方法和策略文章。
相关文章:
在JDK模板设计模式中,找不到一个方法定义了一组要按顺序执行的方法
策略模式的真实例子
其他回答
You probably mean template method pattern. You are right, they serve very similar needs. I would say it is better to use template method in cases when you have a "template" algorithm having defined steps where subclasses override these steps to change some details. In case of strategy, you need to create an interface, and instead of inheritance you are using delegation. I would say it is a bit more powerful pattern and maybe better in accordance to DIP - dependency inversion principles. It is more powerful because you clearly define a new abstraction of strategy - a way of doing something, which does not apply to template method. So, if this abstraction makes sense - use it. However, using template method may give you simpler designs in simple cases, which is also important. Consider which words fit better: do you have a template algorithm? Or is the key thing here that you have an abstraction of strategy - new way of doing something
模板方法的例子:
Application.main()
{
Init();
Run();
Done();
}
这里你继承了application,并替换了init, run和done的操作。
策略的例子:
array.sort (IComparer<T> comparer)
在这里,当编写比较器时,您不继承数组。数组将比较算法委托给比较器。
模板模式类似于策略模式。这两种模式在范围和方法上有所不同。
策略用于允许调用者改变整个算法,比如如何计算不同类型的税,而模板方法用于改变算法中的步骤。因此,策略的粒度更粗。模板允许在操作序列中进行细粒度的控制,但允许这些细节的实现有所不同。
另一个主要区别是策略使用委托,而模板方法使用继承。在Strategy中,算法被委托给主题将引用的另一个xxxStrategy类,但在Template中,您可以继承基类并重写方法来进行更改。
从http://cyruscrypt.blogspot.com/2005/07/template-vs-strategy-patterns.html
模板模式:
模板方法是关于让子类重新定义算法的某些步骤,而不改变基类中定义的算法的主要结构和步骤。 模板模式通常使用继承,因此可以在基类中提供算法的泛型实现,如果需要,子类可以选择覆盖它。
public abstract class RobotTemplate {
/* This method can be overridden by a subclass if required */
public void start() {
System.out.println("Starting....");
}
/* This method can be overridden by a subclass if required */
public void getParts() {
System.out.println("Getting parts....");
}
/* This method can be overridden by a subclass if required */
public void assemble() {
System.out.println("Assembling....");
}
/* This method can be overridden by a subclass if required */
public void test() {
System.out.println("Testing....");
}
/* This method can be overridden by a subclass if required */
public void stop() {
System.out.println("Stopping....");
}
/*
* Template algorithm method made up of multiple steps, whose structure and
* order of steps will not be changed by subclasses.
*/
public final void go() {
start();
getParts();
assemble();
test();
stop();
}
}
/* Concrete subclass overrides template step methods as required for its use */
public class CookieRobot extends RobotTemplate {
private String name;
public CookieRobot(String n) {
name = n;
}
@Override
public void getParts() {
System.out.println("Getting a flour and sugar....");
}
@Override
public void assemble() {
System.out.println("Baking a cookie....");
}
@Override
public void test() {
System.out.println("Crunching a cookie....");
}
public String getName() {
return name;
}
}
注意在上面的代码中,go()算法步骤总是相同的,但是子类可能为执行特定步骤定义不同的配方。
策略模式:
策略模式是指让客户端在运行时选择具体的算法实现。所有算法都是隔离且独立的,但是实现了一个公共接口,并且没有在算法中定义特定步骤的概念。
/**
* This Strategy interface is implemented by all concrete objects representing an
* algorithm(strategy), which lets us define a family of algorithms.
*/
public interface Logging {
void write(String message);
}
/**
* Concrete strategy class representing a particular algorithm.
*/
public class ConsoleLogging implements Logging {
@Override
public void write(String message) {
System.out.println(message);
}
}
/**
* Concrete strategy class representing a particular algorithm.
*/
public class FileLogging implements Logging {
private final File toWrite;
public FileLogging(final File toWrite) {
this.toWrite = toWrite;
}
@Override
public void write(String message) {
try {
final FileWriter fos = new FileWriter(toWrite);
fos.write(message);
fos.close();
} catch (IOException e) {
System.out.println(e);
}
}
}
要获得完整的源代码,请查看我的github存储库。
模板模式用于特定操作具有某些可以根据其他变化的原语行为定义的不变行为。抽象类定义了不变行为,而实现类定义了相关方法。
在策略中,行为实现是独立的——每个实现类定义行为,它们之间没有共享代码。两者都是行为模式,因此被客户以大致相同的方式消费。通常策略只有一个公共方法——execute()方法,而模板可以定义一组公共方法以及一组支持的私有原语,这些原语必须由子类实现。
这两种模式可以很容易地结合使用。您可能有一个策略模式,其中几个实现属于使用模板模式实现的策略家族。
它们都是不同的技术来达到相同的结果,所以问题是在什么时候使用哪一种。
If you are using a framework or library which you do not have access to the source code and you want to change some behaviors of a class, so you have to go for Template Method. That means inheritance simply. If you are developing a class and it is obvious that some parts of the logic needs to be implemented differently to handle various situations, take the Strategy pattern. Strategy is more SOLID than the Template Method. It covers both Dependency Inversion and Open/Close principles. So it is extendable and also easily testable. If you are developing a class and you do not know what changes will happen in the future, divide your logic into separate and single responsible functions as much as possible. Just that. (Neither Template Method nor Strategy).