[Python设计模式] 第10章 怎么出试卷?——模版方法模式
github地址:https://github.com/cheesezh/python_design_patterns
题目
小时候数学老师的随堂测验,都是老师在黑板上写题目,学生在下边抄,然后再做题目。设计一个程序,模拟学生A和B抄题目做试卷的过程。
基础版本
class TestPaperA():
def test_question_1(self):
print("题目1: !+1=?,a.2 b.3 c.4. d.1")
print("我选:a")
def test_question_2(self):
print("题目2: 2+1=?,a.2 b.3 c.4. d.1")
print("我选:b")
def test_question_3(self):
print("题目3: 2+2=?,a.2 b.3 c.4. d.1")
print("我选:c")
class TestPaperB():
def test_question_1(self):
print("题目1: !+1=?,a.2 b.3 c.4. d.1")
print("我选:a")
def test_question_2(self):
print("题目2: 2+1=?,a.2 b.3 c.4. d.1")
print("我选:c")
def test_question_3(self):
print("题目3: 2+2=?,a.2 b.3 c.4. d.1")
print("我选:d")
def main():
print("学生A抄的试卷以及答案")
paper_a = TestPaperA()
paper_a.test_question_1()
paper_a.test_question_2()
paper_a.test_question_3()
print("学生B抄的试卷以及答案")
paper_b = TestPaperB()
paper_b.test_question_1()
paper_b.test_question_2()
paper_b.test_question_3()
main()
学生A抄的试卷以及答案
题目1: !+1=?,a.2 b.3 c.4. d.1
我选:a
题目2: 2+1=?,a.2 b.3 c.4. d.1
我选:b
题目3: 2+2=?,a.2 b.3 c.4. d.1
我选:c
学生B抄的试卷以及答案
题目1: !+1=?,a.2 b.3 c.4. d.1
我选:a
题目2: 2+1=?,a.2 b.3 c.4. d.1
我选:c
题目3: 2+2=?,a.2 b.3 c.4. d.1
我选:d
点评
- 学生A和学生B的考卷题目完全一样,重复代码太多
- 如果老师修改题目,那所有学生都需要改试卷
- 把试卷和答案分离,抽象一个试卷父类,然后学生A和学生B的试卷继承这个父类即可
改进版本1.0——提炼父类
class TestPaper():
def test_question_1(self):
print("题目1: !+1=?,a.2 b.3 c.4. d.1")
def test_question_2(self):
print("题目2: 2+1=?,a.2 b.3 c.4. d.1")
def test_question_3(self):
print("题目3: 2+2=?,a.2 b.3 c.4. d.1")
class TestPaperA(TestPaper):
def test_question_1(self):
super().test_question_1()
print("我选:a")
def test_question_2(self):
super().test_question_2()
print("我选:b")
def test_question_3(self):
super().test_question_3()
print("我选:c")
class TestPaperB(TestPaper):
def test_question_1(self):
super().test_question_1()
print("我选:a")
def test_question_2(self):
super().test_question_2()
print("我选:c")
def test_question_3(self):
super().test_question_3()
print("我选:d")
main()
学生A抄的试卷以及答案
题目1: !+1=?,a.2 b.3 c.4. d.1
我选:a
题目2: 2+1=?,a.2 b.3 c.4. d.1
我选:b
题目3: 2+2=?,a.2 b.3 c.4. d.1
我选:c
学生B抄的试卷以及答案
题目1: !+1=?,a.2 b.3 c.4. d.1
我选:a
题目2: 2+1=?,a.2 b.3 c.4. d.1
我选:c
题目3: 2+2=?,a.2 b.3 c.4. d.1
我选:d
点评
这还是只初步的泛化,两个类中还有类似的代码。比如都有super().test_question_1(),还有print("我选:a"),除了选项不同,其他都相同。
我们既然用了继承,并且认为这个继承是有意义的,那么父类就应该成为子类的模版,所有重复的代码都应该要上升到父类去,而不是让每个子类都去重复。
这就需要使用模版方法来处理。
当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模版方法来处理。
改进版本2.0——提炼细节
from abc import ABCMeta, abstractmethod
class TestPaper():
__metaclass__ = ABCMeta
def test_question_1(self):
print("题目1: !+1=?,a.2 b.3 c.4. d.1")
print("我选:{}".format(self.answer_1()))
@abstractmethod
def answer_1(self):
pass
def test_question_2(self):
print("题目2: 2+1=?,a.2 b.3 c.4. d.1")
print("我选:{}".format(self.answer_2()))
@abstractmethod
def answer_2(self):
pass
def test_question_3(self):
print("题目3: 2+2=?,a.2 b.3 c.4. d.1")
print("我选:{}".format(self.answer_3()))
@abstractmethod
def answer_3(self):
pass
class TestPaperA(TestPaper):
def answer_1(self):
return "a"
def answer_2(self):
return "b"
def answer_3(self):
return "c"
class TestPaperB(TestPaper):
def answer_1(self):
return "a"
def answer_2(self):
return "c"
def answer_3(self):
return "d"
main()
学生A抄的试卷以及答案
题目1: !+1=?,a.2 b.3 c.4. d.1
我选:a
题目2: 2+1=?,a.2 b.3 c.4. d.1
我选:b
题目3: 2+2=?,a.2 b.3 c.4. d.1
我选:c
学生B抄的试卷以及答案
题目1: !+1=?,a.2 b.3 c.4. d.1
我选:a
题目2: 2+1=?,a.2 b.3 c.4. d.1
我选:c
题目3: 2+2=?,a.2 b.3 c.4. d.1
我选:d
点评
此时要有更多的学生来答试卷,只是在试卷的模版上填写选择题的选项答案,即可。
模版方法
模版方法,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤[DP]。
from abc import ABCMeta, abstractmethod
class AbstractClass():
"""
抽象模版类,定义并实现了一个模版方法,这个模版方法一般是一个具体的算法,
它定义了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到
子类实现。当然,顶级逻辑也可能调用一些具体方法。
"""
__metaclass__ = ABCMeta
@abstractmethod
def primitive_operation_1(self):
"""
抽象操作1,放到子类去实现
"""
pass
@abstractmethod
def primitive_operation_2(self):
"""
抽象操作2,放到子类去实现
"""
pass
def template_method(self):
"""
具体模版方法,定义了顶级逻辑骨架
"""
self.primitive_operation_1()
self.primitive_operation_2()
class ConcreteClassA(AbstractClass):
"""
具体类A,给出抽象方法的不同实现
"""
def primitive_operation_1(self):
print("具体类A的操作1")
def primitive_operation_2(self):
print("具体类A的操作2")
class ConcreteClassB(AbstractClass):
"""
具体类B,给出抽象方法的不同实现
"""
def primitive_operation_1(self):
print("具体类B的操作1")
def primitive_operation_2(self):
print("具体类B的操作2")
cls = ConcreteClassA()
cls.template_method()
cls = ConcreteClassB()
cls.template_method()
具体类A的操作1
具体类A的操作2
具体类B的操作1
具体类B的操作2
点评
- 模版方法通过把不变的行为搬移到超类,去除子类中的重复代码来体现它的优势
- 模版方法提供了一个很好的代码复用平台
- 当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。我们通过模版方法模式把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠
[Python设计模式] 第10章 怎么出试卷?——模版方法模式的更多相关文章
- [Python设计模式] 第12章 基金理财更省事——外观模式
github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟股民直接炒股的代码,比如股民投资了股票1,股票2,股票3,国债 ...
- [Python设计模式] 第22章 手机型号&软件版本——桥接模式
github地址:https://github.com/cheesezh/python_design_patterns 紧耦合程序演化 题目1 编程模拟以下情景,有一个N品牌手机,在上边玩一个小游戏. ...
- [Python设计模式] 第2章 商场收银软件——策略模式
github地址: https://github.com/cheesezh/python_design_patterns 题目 设计一个控制台程序, 模拟商场收银软件,根据客户购买商品的单价和数量,计 ...
- [Python设计模式] 第25章 联合国维护世界和平——中介者模式
github地址:https://github.com/cheesezh/python_design_patterns 题目背景 联合国在世界上就是中介者的角色,各国之间的关系复杂,类似不同的对象和对 ...
- [Python设计模式] 第23章 烤串的哲学——命令模式
github地址:https://github.com/cheesezh/python_design_patterns 题目1 用程序模拟,顾客直接向烤串师傅提需求. class Barbecuer( ...
- JS常用的设计模式(10)——模版方法模式
模式方法是预先定义一组算法,先把算法的不变部分抽象到父类,再将另外一些可变的步骤延迟到子类去实现.听起来有点像工厂模式( 非前面说过的简单工厂模式 ). 最大的区别是,工厂模式的意图是根据子类的实现最 ...
- Python设计模式——模版方法模式
1.模版方法模式 做题的列子: 需求:有两个学生,要回答问题,写出自己的答案 #encoding=utf-8 __author__ = 'kevinlu1010@qq.com' class Stude ...
- 【java设计模式】(10)---模版方法模式(案例解析)
一.概念 1.概念 模板方法模式是一种基于继承的代码复用技术,它是一种类行为型模式. 它定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的 ...
- 第13章 模版方法模式(Template Method)
原文 第13章 模版方法模式(Template Method) 模板模式 模板模式 举例:模拟下数据库的update方法,先删除在插入. 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
随机推荐
- bzoj2152 树分治
还是太菜了,自己写的wa,但是找不到哪里错了,, 感觉现在学树分治早了点..以后回来再看吧 /* 多少点对之间的路径是3的倍数 */ #include<iostream> #include ...
- hdu4052矩形面积并
建模需要注意下细节,,这是做扫描线的惯例,就是最好把模型建立在笛卡尔坐标系上 剩下的看链接和注释https://blog.csdn.net/shiqi_614/article/details/7983 ...
- (四)CXF处理JavaBean以及复合类型
前面讲的是处理简单类型,今天这里来讲下CXF处理JavaBean以及复合类型,比如集合: 这里实例是客户端传一个JavaBean,服务器端返回集合类型: 在原来的项目实例基础上,我们先创建一个实体类U ...
- 性能测试十七:liunx下jmeter结果报表、html报表
控制台日志,只能看出整体的数据,若只是测单接口,这个最好用,但若有多个接口时,无法分别展示,所以需要换另外一种报表 四种方式来获取Jmeter的结果报表 一.在GUI模式下跑Jmeter的脚本,用tp ...
- python 全栈开发,Day29(昨日作业讲解,模块搜索路径,编译python文件,包以及包的import和from,软件开发规范)
一.昨日作业讲解 先来回顾一下昨日的内容 1.os模块 和操作系统交互 工作目录 文件夹 文件 操作系统命令 路径相关的 2.模块 最本质的区别 import会创建一个专属于模块的名字, 所有导入模块 ...
- istringstream、ostringstream、stringstream 类介绍 和 stringstream类 clear函数的真正用途
istringstream.ostringstream.stringstream 类介绍 和 stringstream类 clear函数的真正用途 来源: http://blog.csdn.net/T ...
- MySQL索引失效的几种情况
1.索引不存储null值 更准确的说,单列索引不存储null值,复合索引不存储全为null的值.索引不能存储Null,所以对这列采用is null条件时,因为索引上根本 没Null值,不能利用到索引, ...
- Phone List HDU1671
字典树的包含与不包含关系 #include<bits/stdc++.h> using namespace std; ][]; ]; ; bool insert1( char *word ) ...
- 分布式系统理论--CAP理论、BASE理论
问题的提出 在计算机科学领域,分布式一致性是一个相当重要且被广泛探索与论证问题,首先来看三种业务场景. 1.火车站售票 假如说我们的终端用户是一位经常坐火车的旅行家,通常他是去车站的售票处购买车票,然 ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-6 Cornell box
Chapter 6:Rectangles and Lights 今天,我们来学习长方形区域光照 先看效果 light 首先我们需要设计一个发光的材质 /// light.hpp // ------- ...