既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模板,所有重复的代码都应该要上升到父类去,而不是让每个子类都去重复。
当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模板方法模式来处理。
模板方法模式(Template Method),定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法模式需要开发抽象类和具体子类的设计师之间的协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻辑步骤。代表这些具体逻辑步骤的方法称作基本方法(primitive method);而将这些基本方法汇总起来的方法叫做模板方法(template method)。模板方法所代表的行为称为顶级行为,其逻辑称为顶级逻辑。
这里涉及到两个角色:
抽象模板角色(其实不一定要是抽象类,如Android中的view类)有如下责任:
1.定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。
2.定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
具体模板角色有如下责任:
1.实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。
2.每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
模板模式的关键是:子类可以置换掉父类的可变部分,但是子类却不可以改变模板方法所代表的顶级逻辑。
例子,模板方法:
public abstract class TemplateMethod { public abstract void primitiveOperation1(); public abstract void primitiveOperation2(); // 模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,推迟到子类实现 public void templateMethod() { primitiveOperation1(); // ... 其他操作 primitiveOperation2(); } }
public class PrimitiveMethodA extends TemplateMethod { @Override public void primitiveOperation1() { System.out.println("用剪刀剪纸箱"); } @Override public void primitiveOperation2() { System.out.println("用胶水封纸箱"); } }
public class PrimitiveMethodB extends TemplateMethod { @Override public void primitiveOperation1() { System.out.println("用手撕纸箱"); } @Override public void primitiveOperation2() { System.out.println("用胶带封纸箱"); } }
TemplateMethod methodA = new PrimitiveMethodA(); methodA.templateMethod();
模板方法模式是通过把不变行为搬移到父类,去除子类中的重复代码来体现它的优势。
模板方法模式就是提供了一个很好的代码复用平台。
当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。通过模板方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。