10.3 提炼代码
老师出一份试卷,打印多份,学生填写答案即可。
把试题和答案分享,抽象出分类,让子类继承,公共试题代码写在父类类中,即可。
但是这样的话,学生子类中还是有重复的代码,比如base.testQuestion1()等等。
所有重复的代码都应该要上升到父类去,而不是让每个子类都去重复。
场景:
当我们完成某一细节层次一直的一个过程或一系列步骤,但个别步骤在更详细层次上的实现可能不同时,通常考虑用模板方法模式处理。
实现:
在父类变化的地方,加一个抽象方法,子类实现这个抽象方法,将变化的逻辑写入这个方法中。
//父类中的方法
public class TestPaper {
public void testQuestion1(){
println("炼成倚天剑、屠龙刀的玄铁可能是[] a.铸铁 b.马口铁 c.高速合金钢 d.碳素纤维");
println("答案:" + answer1()); //改成一个抽象方法
}
//给继承的子类重写,每个人答案都是不同的
protected abstract String answer1();
}
子类实现很简单,重写抽象方法,其他不用管
class TestPaperA extends TestPaper {
protected String answer1(){
return "b";
}
protected String answer2(){
return "c";
}
}
//...可以有多个学生继承
客户端
public static void main(String[] args){
println("学生A的试卷");
TestPaper studentA = new TestPaperA();
studentA.testQuestion1();
studentA.testQuestion2();
studentA.testQuestion3();
}
即使更多学生案卷,也只是在选择答案,这是每个人试卷的唯一不同。
但是除了学生填写的选项不同之外,还是每个人的姓名也是不同的。要做到最大复用。
10.4 模板方法模式
定义
定义一个操作中算法的骨架,将一些步骤延迟到子类中。模板方法使子类可不改变一个算法结构即可重定义该算法的某些特定步骤。
AbstractClass是抽象类,也就是一抽象模板,定义并实现了一个模板方法。模板方法是一个具体方法,给出了一个顶级逻辑的骨架,而逻辑组成步骤在相应的抽象方法中,推迟到子类实现。
public abstract class AbstractClass {
//抽象方法,放到子类实现
public abstract void operation1();
public abstract void operation2();
//模板方法,给出逻辑骨架,内部方法都推迟到子类实现
public void templateMethod(){
operation1();
operation2();
}
}
ConcreteClass,实现父类定义的一个或多个抽象方法,ConcreteClass可以有多个,每一个实现的抽象方法内部逻辑各不相同。
public class ConcreteClassA extends AbstractClass {
@Override
public void operation1(){
println("具体类A方法1的实现");
}
@Override
public void operation2(){
println("具体类A方法2的实现");
}
}
//...不同的ConcreteClass
客户端调用
public static void main(String[] args){
AbstractClass c;
c = new ConcreteClassA();
c.templateMethod();
c = new ConcreteClassB();
c.templateMethod();
}
10.5 模板方法模式特点
通过把不变行为搬移到父类,去除子类中的重复代码体现优势。
模板方法模式提供了很好的代码复用平台。
帮助子类摆脱重复的不变行为的纠缠。