模板方法模式
前序
相信大家已经对上次小菜投递简历的过程已经非常了解了,这回小菜收到了XX公司的面试通知并去完成了面试。回来时大鸟问小菜感觉如何?小菜回答到:“书到用时方恨少呀,英语太烂,没办法。”然后两人讨论到以前微软的MCSE和MCSD认证考试,在刚开始时有很多教育机构弄到了题库,并承诺保证通过,不通过不收费。于是小菜的一位同学并不是计算机专业的,靠着背题库通过了这个世界最大软件公司的开发技术认证。
最后大鸟说到他小时候因为抄错题而没考好,回家父母说他不认真学习。其实问题并不在这里,如果使用标准化的考试卷也就不会产生抄错题的苦恼。
于是大鸟让小菜写了一份抄题的代码。
小菜的第一份作业
#include <stdio.h>
// 学生甲抄的试卷
class TestPaperA
{
public:
void TestQuestion1()
{
printf("杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是【】a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳塑纤维\n");
printf("答案: b\n");
}
void TestQuestion2()
{
printf("杨过、程英、陆无双铲除了情花,造成【】a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化\n");
printf("答案: a\n");
}
void TestQuestion3()
{
printf("蓝凤凰致使华山师徒、桃谷六神呕吐不止,如果你是大夫,会给他们开什么药【】a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的升牛奶 e.以上全不对\n");
printf("答案: c\n");
}
};
// 学生乙抄的试卷
class TestPaperB
{
public:
void TestQuestion1()
{
printf("杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是【】a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳塑纤维\n");
printf("答案: d\n");
}
void TestQuestion2()
{
printf("杨过、程英、陆无双铲除了情花,造成【】a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化\n");
printf("答案: b\n");
}
void TestQuestion3()
{
printf("蓝凤凰致使华山师徒、桃谷六神呕吐不止,如果你是大夫,会给他们开什么药【】a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的升牛奶 e.以上全不对\n");
printf("答案: a\n");
}
};
int main()
{
printf("学生甲抄的试卷:\n");
TestPaperA studentA;
studentA.TestQuestion1();
studentA.TestQuestion2();
studentA.TestQuestion3();
printf("学生乙抄的试卷:\n");
TestPaperB studentB;
studentB.TestQuestion1();
studentB.TestQuestion2();
studentB.TestQuestion3();
return 0;
}
写完后小菜说到:“这两份试卷非常类似,除了答案不同,没什么不一样,这样写又容易错,又难以维护。”
“说的对,如果老师突然要改题目,那两个人就都需要改代码,如果某人抄错了,那真是糟糕至极。那你说怎么办?”
“老师出一份试卷,打印多份,然后让学生填写答案就可以了。在这里应该就把尸体和答案分享,抽象出一个父类,让两个子类继承于它,公共的试题代码写到父类当中,就可以了。”
模板方法模式
模板方法模式准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。
实现方法(UML类图)
实现代码
#include <stdio.h>
class TestPaper
{
public:
void TestQuestion1()
{
printf("杨过得到,后来给了郭靖,炼成倚天剑、屠龙刀的玄铁可能是【】a.球磨铸铁 b.马口铁 c.高速合金钢 d.碳塑纤维\n");
printf("答案: %c\n",Answer1());
}
void TestQuestion2()
{
printf("杨过、程英、陆无双铲除了情花,造成【】a.使这种植物不再害人 b.使一种珍稀物种灭绝 c.破坏了那个生物圈的生态平衡 d.造成该地区沙漠化\n");
printf("答案: %c\n",Answer2());
}
void TestQuestion3()
{
printf("蓝凤凰致使华山师徒、桃谷六神呕吐不止,如果你是大夫,会给他们开什么药【】a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的升牛奶 e.以上全不对\n");
printf("答案: %c\n",Answer3());
}
protected:
virtual char Answer1()=0;
virtual char Answer2()=0;
virtual char Answer3()=0;
};
class TestPaperA : public TestPaper
{
protected:
virtual char Answer1()
{
return 'b';
}
virtual char Answer2()
{
return 'c';
}
virtual char Answer3()
{
return 'a';
}
};
class TestPaperB : public TestPaper
{
protected:
virtual char Answer1()
{
return 'c';
}
virtual char Answer2()
{
return 'a';
}
virtual char Answer3()
{
return 'a';
}
};
int main()
{
printf("学生甲抄的试卷:\n");
TestPaper* studentA = new TestPaperA();
studentA->TestQuestion1();
studentA->TestQuestion2();
studentA->TestQuestion3();
printf("学生乙抄的试卷:\n");
TestPaper* studentB = new TestPaperB();
studentB->TestQuestion1();
studentB->TestQuestion2();
studentB->TestQuestion3();
delete studentA;
delete studentB;
return 0;
}
运行结果
所有文件打包下载