请问有人能解释一下模板方法模式和策略模式的区别吗?
据我所知,它们在99%的情况下是相同的 - 唯一的区别在于模板方法模式使用抽象类作为基类,而策略模式则使用接口,由每个具体的策略类实现。
然而,在客户端看来,它们以完全相同的方式被调用 - 这样正确吗?
请问有人能解释一下模板方法模式和策略模式的区别吗?
据我所知,它们在99%的情况下是相同的 - 唯一的区别在于模板方法模式使用抽象类作为基类,而策略模式则使用接口,由每个具体的策略类实现。
然而,在客户端看来,它们以完全相同的方式被调用 - 这样正确吗?
模板方法是让子类重新定义算法的某些步骤,而不改变基类中定义的算法的主要结构和步骤。 模板模式通常使用继承,因此可以在基类中提供算法的通用实现,如果需要,子类可以选择覆盖它。
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存储库。
模板模式类似于策略模式。这两种模式在范围和方法论上有所不同。
策略用于允许调用者变化整个算法,例如如何计算不同类型的税,而模板方法用于变化算法中的步骤。因此,策略更加粗粒度。模板允许在操作序列中进行更细粒度的控制,并且允许这些细节的实现发生变化。
另一个主要区别是策略使用委托,而模板方法使用继承。在策略中,算法被委托给另一个xxxStrategy类,该主题将具有对其的引用,但是在模板中,您可以对基类进行子类化并覆盖方法以进行更改。
来自http://cyruscrypt.blogspot.com/2005/07/template-vs-strategy-patterns.html
策略设计模式
模板方法设计模式
两种技术都是实现相同结果的不同方式,所以问题在于何时使用哪种技术。
CalculateSomething(){
int i = 0;
i = Step1(i);
i++;
if (i> 10) i = 5;
i = Step2(i);
return i;
Step1和Step2方法的实现可以由派生类提供。
在策略模式中,基类没有提供任何实现(这就是为什么基类在类图中真正是一个接口的原因)
经典的例子是排序。根据需要排序的对象数量创建适当的算法类(合并、冒泡、快速等),并将整个算法封装在每个类中。
现在我们能否将排序实现为模板方法?当然可以,但您不会找到太多/任何通用性可抽象出并放置在基本实现中。因此,这违背了模板方法模式的目的。
策略模式被暴露为接口,而模板方法则是抽象类。这在框架中通常被广泛使用。 例如, Spring框架的MessageSource类是用于解析消息的策略接口。客户端使用此接口的特定实现(策略)。
同样的接口AbstractMessageSource的抽象实现具有解析消息的通用实现,并公开resolveCode()抽象方法,以便子类可以按照自己的方式实现它们。AbstractMessageSource是模板方法的一个例子。
模板方法模式适用于澄清整个算法步骤,然而策略模式则适用于灵活性和可重用性,因此如果需要,您可以将策略组合在一起,例如:JDK8中的许多功能接口,如Comparator.reversed().thenComparing(Comparator)
是策略的角色。
模板方法模式更注重高内聚性,但策略模式与上下文对象松耦合以分离关注点。
策略易于维护,因为上下文不知道具体的策略,只要主要算法在上下文中改变不会影响策略。另一方面,如果在抽象模板类中更改算法的框架可能会影响其子类的升级。
我认为主要的区别在于模板需要一个执行某些操作的算法,但是假设在该算法中间你想运行不同的行为,那么你可以发送一个接口的实现来使该算法在运行时动态生成。
但是使用策略模式,你实际上有完全不同的算法执行,而不仅仅是算法的变量,然后你选择要运行哪个算法,但是模板只有一种带有变体的算法。
最终,你可以按照自己的意愿进行实现并将模板用作策略,反之亦然,但我认为存在区别。