大话设计模式之模板方法模式总结-java实现

注:示例来自《大话设计模式》

现有需求如下 老师随堂测验 在黑板上抄题目 学生先抄题目 然后再做答案 代码初步实现如下

学生甲抄的试卷类

package Test10;

//学生甲抄的试卷
public class TestPaperA {

    //试题1
    public void TestQuestion1()
    {
        System.out.println(" 杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维 ");
        System.out.println("答案:b");
    }
    //试题2
    public void TestQuestion2()
    {
        System.out.println(" 杨过、程英、陆无双铲除了情花,造成[ ] a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化  ");
        System.out.println("答案:a");
    }
    //试题3
    public void TestQuestion3()
    {
        System.out.println(" 蓝凤凰的致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ] a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对   ");
        System.out.println("答案:c");
    }

}

学生乙抄的试卷类

package Test10;

//学生乙抄的试卷
public class TestPaperB {

    //试题1
    public void TestQuestion1()
    {
        System.out.println(" 杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维 ");
        System.out.println("答案:d");
    }
    //试题2
    public void TestQuestion2()
    {
        System.out.println(" 杨过、程英、陆无双铲除了情花,造成[ ] a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化  ");
        System.out.println("答案:b");
    }
    //试题3
    public void TestQuestion3()
    {
        System.out.println(" 蓝凤凰的致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ] a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对   ");
        System.out.println("答案:a");
    }

}

客户端代码

package Test10;

public class Program {

    public static void main(String[] args) {

        System.out.println("学生甲抄的试卷:");
        TestPaperA studentA = new TestPaperA();
        studentA.TestQuestion1();
        studentA.TestQuestion2();
        studentA.TestQuestion3();

        System.out.println("学生乙抄的试卷:");
        TestPaperB studentB = new TestPaperB();
        studentB.TestQuestion1();
        studentB.TestQuestion2();
        studentB.TestQuestion3();

    }

}

上面的代码 学生甲和学生乙两个抄试卷类非常相似 这样写容易错 又难以维护 下面进行重构 抽取公共部分 代码如下

试卷父类

package Test10;

//金庸小说考题试卷
public class TestPaper {

    public void TestQuestion1()
    {
        System.out.println(" 杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维 ");
    }

    public void TestQuestion2()
    {
        System.out.println(" 杨过、程英、陆无双铲除了情花,造成[ ] a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化  ");
    }

    public void TestQuestion3()
    {
        System.out.println(" 蓝凤凰的致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ] a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对   ");
    }

}

学生子类

package Test10;

//学生甲抄的试卷
public class TestPaperA extends TestPaper {

    public void TestQuestion1()
    {
        super.TestQuestion1();
        System.out.println("答案:b");
    }

    public void TestQuestion2()
    {
        super.TestQuestion2();
        System.out.println("答案:b");
    }

    public void TestQuestion3()
    {
        super.TestQuestion3();
        System.out.println("答案:b");
    }

}
package Test10;

//学生乙抄的试卷
public class TestPaperB extends TestPaper {

    public void TestQuestion1()
    {
        super.TestQuestion1();
        System.out.println("答案:b");
    }

    public void TestQuestion2()
    {
        super.TestQuestion2();
        System.out.println("答案:b");
    }

    public void TestQuestion3()
    {
        super.TestQuestion3();
        System.out.println("答案:b");
    }

}

客户端代码同上

上面的代码只是初步的泛化 两个学生的类里面还是有重复的代码

我们既然用了继承 并且想让这个继承有意义 就应该要成为子类的模板 所有重复的代码都应该要上升到父类去 而不是让每个子类都去重复

当我们要完成在某一细节层次一致的一个过程或一系列步骤 但其个别步骤在更详细的层次上的实现可能不同时 我们通常考虑用模板方法模式来处理 代码实现如下

试卷父类

package Test10;

//金庸小说考题试卷
public abstract class TestPaper {

    public void TestQuestion1()
    {
        System.out.println(" 杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是[ ] a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳素纤维 ");
        System.out.println("答案:" + Answer1());
    }

    public void TestQuestion2()
    {
        System.out.println(" 杨过、程英、陆无双铲除了情花,造成[ ] a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化  ");
        System.out.println("答案:" + Answer2());
    }

    public void TestQuestion3()
    {
        System.out.println(" 蓝凤凰的致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[ ] a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对   ");
        System.out.println("答案:" + Answer3());
    }

    protected abstract String Answer1();

    protected abstract String Answer2();

    protected abstract String Answer3();

}

学生子类

package Test10;

//学生甲抄的试卷
public class TestPaperA extends TestPaper {

    @Override
    protected String Answer1()
    {
        return "b";
    }

    @Override
    protected String Answer2()
    {
        return "c";
    }

    @Override
    protected String Answer3()
    {
        return "a";
    }

}
package Test10;

//学生乙抄的试卷
public class TestPaperB extends TestPaper {

    @Override
    protected String Answer1()
    {
        return "c";
    }

    @Override
    protected String Answer2()
    {
        return "a";
    }

    @Override
    protected String Answer3()
    {
        return "a";
    }

}

客户端代码

package Test10;

public class Program {

    public static void main(String[] args) {

        System.out.println("学生甲抄的试卷:");
        TestPaper studentA = new TestPaperA();
        studentA.TestQuestion1();
        studentA.TestQuestion2();
        studentA.TestQuestion3();

        System.out.println("学生乙抄的试卷:");
        TestPaper studentB = new TestPaperB();
        studentB.TestQuestion1();
        studentB.TestQuestion2();
        studentB.TestQuestion3();

    }

}

模板方法模式 定义一个操作中的算法的骨架 而将一些步骤延迟到子类中 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤

模板方法模式是通过把不变行为搬移到超类 去除子类中的重复代码来体现它的优势 模板方法模式就是提供了一个很好的代码复用平台

当不变的和可变的行为在方法的子类实现中混合在一起的时候 不变的行为就会在子类中重复出现 通过模板方法模式把这些行为搬移到单一的地方 这样就帮助子类摆脱重复的不变行为的纠缠

缺点 每个不同的实现都需要定义一个子类 这会导致类的个数的增加 设计更加抽象

猜你喜欢

转载自blog.csdn.net/qq_26814945/article/details/82346114