模板方法模式的介绍
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。实质上就类似于继承,将将各个子类中的重复代码移动到抽象类或接口中,提高了代码的复用性。
模板方法模式参与角色
参与角色 | 功能 |
---|---|
抽象类(接口)角色 | 将所有重复的不可变的行为放在该类中 ,并且在内部定义了一个模板方法(顶级逻辑骨架) |
子类角色 | 实现了抽象接口中逻辑骨架指定的方法,使得顶级逻辑的实现各不相同 |
模板方法模式的UML
相关案例
案例如下:现有两类玩具A和B,他们的制造过程是先制造上半身,然后下半身,最后组装,不同的是玩具A是娃娃类,B类是宠物类。下面我们将用模板方法模式来实现这个案例。
题目分析:从该题中我们可以得知两类玩具的制造组装方法一致,只是具体的制造内容不一致,所以我们可以得出一个抽象类,并且创建三个抽象方法制造上半身、制造下半身和组装,然后在设计一个方法在内部调用了上面的三个抽象方法(顶级逻辑骨架),这样我们就可以在子类中实现三个抽象方法后直接调用父类的模板方法创建各自的对象。
抽象类角色代码书写:
package templateMethodDesign;
/**
* @Method 该类是一个抽象类,内部定义了三个抽象的方法,并且定义了一个非抽象的模板方法(顶级逻辑骨架)。
*/
public abstract class AbstracFac {
/**抽象方法——制作上半身*/
public abstract void makeUpper();
/**抽象方法——制作下半身*/
public abstract void makeLow();
/**抽象方法——组装*/
public abstract void assemble();
/**模板方法,内部调用了三个抽象方法*/
public void templateMethod() {
this.makeUpper();
this.makeLow();
this.assemble();
}
}
具体角色类代码
(1)A类产品
package templateMethodDesign;
/**
* @Introdcution 该类是产品A类,继承了AbstractFac,使用自己的方式实现了三个抽象的方法
*
*/
public class ProductA extends AbstracFac{
/**重写方法*/
@Override
public void makeUpper(){
System.out.println("成功制作A产品的上半身");
}
@Override
public void makeLow() {
System.out.println("成功制作A产品的下半身");
}
@Override
public void assemble() {
System.out.println("组装成功");
}
}
(2)B类产品
package templateMethodDesign;
/**
* @Introduction 该类是B类产品的制造类,继承了AbstractFac,实现了三个抽象的方法
*/
public class ProductB extends AbstracFac{
/**重写方法*/
@Override
public void makeUpper() {
System.out.println("成功制作B产品上半身");
}
@Override
public void makeLow() {
System.out.println("成功制作B产品下半身");
}
@Override
public void assemble() {
System.out.println("组装成功");
}
}
用户界面模拟代码:
package templateMethodDesign;
/**
* @Introduction 该类是模拟用户界面,用于创建不同的产品
*/
public class User {
public static void main(String[] args) {
AbstracFac factory; //相当与一个工厂,既可以制作A,又可以制作B
factory=new ProductA(); //创建A产品并组装
factory.templateMethod();
factory=new ProductB();
factory.templateMethod(); //创建B产品并组装
}
}
案例分析
我们可以看出模板方法模式其实本质上就是继承的一种使用,不过如果想使用模板方法模式,我们需要子类直接的顶级逻辑骨架(就是逻辑上具有一致性),只是在具体实现上不同,就像炒菜一样,大致的流程差不多,但每一菜需要放的调料和火候不一致。
在上面的案例中具体的子类产品A和产品B只是实现了他们不同的地方(制作上半身、下半身和组合),其余的都在抽象类角色中进行实现,就相当于将父类的方法推迟到子类中实现,而且如果我们需要改变一些具体的实现过程,比如我们需要更改A产品的颜色我们只需要在A产品类中进行更改,无需涉及到父类逻辑的修改,是模块直接的独立性提高了。
模板方法模式的优缺点
优点;
- 提高了代码的复用性。这是该模式的最主要的优点,在该模式中尽可能的将所有重复代码放入父类中。
- 提高了可维护性,对于维护者来说,如果要增加一些细节方面的功能,不对逻辑方面进行修改,那么他只需要更改子类的实现方法,无需了解父类的顶级逻辑流程。
- 将行为和实现分离。在该模式中行为(逻辑)在父类中,而实现在子类中,使得代码质量更高。
缺点:
- 在客户端需要知道所有具体的子类。不利于将业务逻辑和界面逻辑进行分离
- 如果需要实现的功能过多则会使得子类过于庞大(每一个不同的实现都需要一个不同的子类)