设计模式 - 模版模式
一、引入
想象一下你在制作不同种类的饮料,比如咖啡和茶。虽然它们的制作步骤会有些不同,但也有一些共同的操作,比如烧开水、倒入杯子等。
模板模式就是把这些共同的操作先规定好,形成一个"模板",然后在具体制作每种饮料时,只需要把特殊的步骤(比如冲泡咖啡或者茶)加入到模板中就行了。
这样做的好处是,你不用每次都重新写一遍那些相同的操作,只需要关心每种饮料特有的步骤就行了。同时,模板模式还保证了制作饮料的步骤是按照一定顺序来进行的,这样就不容易出错。
总的来说,模板模式就是先规定一个共同的模板,然后根据具体情况来填充模板中的细节,这样可以保证一些共同的操作在不同情况下都能正常运行。
二、概念
模板模式(Template Pattern)是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的具体实现延迟到了子类中。
在模板模式中,定义一个算法的骨架,其中一些步骤的具体实现由子类完成。这样,可以使得在不改变算法结构的前提下,可以重新定义算法中的某些步骤。
三、基本结构
- 抽象类(Abstract Class) :定义了算法的骨架,其中包含了一系列的步骤,这些步骤的具体实现将由子类来完成。
- 具体子类(Concrete Class) :实现了抽象类中定义的具体步骤,完成了算法的具体实现。
四、示例代码
csharp
/**
* 抽象类
*
* @author zf
*/
public abstract class Beverage {
// 制作饮料的步骤
public final void prepareBeverage() {
//烧开水
boilWater();
//酿造
brew();
//倒入杯子
pourInCup();
//添加调料
addCondiments();
}
protected abstract void brew();
protected abstract void addCondiments();
// 公共的步骤
private void boilWater() {
System.out.println("烧开水");
}
private void pourInCup() {
System.out.println("倒入杯子");
}
}
csharp
/**
* 具体的实现类 : 咖啡
*
* @author zf
*/
public class Coffee extends Beverage {
@Override
protected void brew() {
System.out.println("手磨咖啡");
}
@Override
protected void addCondiments() {
System.out.println("添加牛奶或糖");
}
}
csharp
/**
* 具体的实现类 : 养生茶
*
* @author zf
*/
public class Tea extends Beverage {
@Override
protected void brew() {
System.out.println("沏茶");
}
@Override
protected void addCondiments() {
System.out.println("添加枸杞");
}
}
java
/**
* 客户端
*
* @author zf
*/
public class Client {
public static void main(String[] args) {
Beverage coffee = new Coffee();
coffee.prepareBeverage();
Beverage tea = new Tea();
tea.prepareBeverage();
}
}
五、用途
-
定义一个算法的框架:
- 模板方法模式定义了一个算法的骨架,规定了算法的结构,但具体的实现细节可以由子类来完成。这样可以保证在不改变算法结构的前提下,可以重新定义算法中的某些步骤。
-
避免代码重复:
- 通过将一些通用的操作放在抽象类中,可以避免在每个具体子类中重复编写相同的代码。
-
保持一致性:
- 模板方法模式可以确保算法中的某些步骤按照固定的顺序进行,从而保持了一致性。
在日常开发中,模板方法模式经常用于以下场景:
-
框架设计:
- 框架中通常会定义一些抽象类或接口,其中包含了算法的框架(模板方法),具体的实现由框架的使用者来完成。
-
算法实现:
- 当多个算法有共同的一些步骤时,可以使用模板方法模式来抽象这些共同的步骤,具体的算法细节由子类来实现。
-
库函数:
- 在库函数中,可以使用模板方法模式来规定一些通用的操作,具体的实现由调用者来提供。
六、总结
优点:
- 代码复用:模板模式将一些共同的操作抽象出来,形成一个模板,可以在多个地方重复使用,避免了重复编写相似的代码。
- 提高扩展性:通过定义一个算法的骨架,可以在不改变算法结构的前提下,重新定义算法中的某些步骤,从而提高了扩展性。
- 保持一致性:模板模式可以保证一些操作按照固定的顺序进行,从而保持了一致性。
- 降低了类之间的耦合度:抽象类中定义了算法的结构,具体的实现由子类来完成,使得子类与抽象类之间的耦合度降低。
缺点:
- 过度使用:如果过度使用模板模式,可能会导致代码变得复杂,不容易理解和维护。
- 不适合所有情况:并不是所有的情况都适合使用模板模式,例如,如果算法的步骤比较简单,没有太多共同的操作,可能就不需要使用模板模式。
- 违反了开闭原则:如果需要修改模板中的基本算法结构,可能会影响到所有子类,违反了开闭原则(对扩展开放,对修改关闭)。
总的来说,模板模式是一种非常有用的设计模式,可以提高代码的复用性和可维护性,但需要合适地使用,避免过度使用。同时,也需要注意在设计时考虑到可能的扩展和变化,以避免违反开闭原则。