python-模板方法模式
源码地址:https://github.com/weilanhanf/PythonDesignPatterns
说明:
模板方法模式时行为模式中比较简单的设计模式之一。模板方法关注这样的一类行为:该类行为在执行过程中拥有大致相同的动作次序,只是动作在实现的具体细节上有所差异。例如:泡茶和泡咖啡,泡茶:把水煮沸,沸水加入茶叶,把倒进杯子。泡咖啡:把水煮沸,用沸水冲咖啡粉,把咖啡倒进杯子。这样看来泡茶和泡咖啡的三个步骤基本相似。我们可以报这一类行为抽象成一个算法,并将其中的动作序列按1其先后顺序也抽象出来作为该算法的一些步骤。至于这些步骤的实现细节,则有算法的子类去实现。
模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法模式 是一种基于继承的代码复用技术 ,将一些复杂流程的实现步骤封装在一系列基本方法中 ,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。

模板方法模式的结构
模板方法模式包含以下两个角色: AbstractClass(抽象类) ConcreteClass(具体子类)
模板方法模式的实现:
模板方法 (Template Method)
基本方法 (Primitive Method) :1、抽象方法(Abstract Method)2、 具体方法(Concrete Method) 3、钩子方法(Hook Method) :“挂钩”方法和空方法
实例:
投资股票是种常见的理财方式,我国股民越来越多,实时查询股票的需求也越来越大。今天,我们通过一个简单的股票查询客户端来认识一种简单的设计模式:模板模式。
根据股票代码来查询股价分为如下几个步骤:登录、设置股票代码、查询、展示。
#构造如下的虚拟股票查询器:
class StockQueryDevice():
stock_code=""
stock_price=0.0
def login(self,usr,pwd):
pass
def setCode(self,code):
self.stock_code=code
def queryPrice(self):
pass
def showPrice(self):
pass #根据不同的查询机构和方式来通过继承的方式实现其的股票查询器类。
#WebA和WebB的查询器类可以构造如下:
class WebAStockQueryDevice(StockQueryDevice):
def login(self,usr,pwd):
if usr=="myStockA" and pwd=="myPwdA":
print "Web A:Login OK... user:%s pwd:%s"%(usr,pwd)
return True
else:
print "Web A:Login ERROR... user:%s pwd:%s"%(usr,pwd)
return False
def queryPrice(self):
print "Web A Querying...code:%s "%self.stock_code
self.stock_price=20.00
def showPrice(self):
print "Web A Stock Price...code:%s price:%s"%(self.stock_code,self.stock_price)
class WebBStockQueryDevice(StockQueryDevice):
def login(self,usr,pwd):
if usr=="myStockB" and pwd=="myPwdB":
print "Web B:Login OK... user:%s pwd:%s"%(usr,pwd)
return True
else:
print "Web B:Login ERROR... user:%s pwd:%s"%(usr,pwd)
return False
def queryPrice(self):
print "Web B Querying...code:%s "%self.stock_code
self.stock_price=30.00
def showPrice(self):
print "Web B Stock Price...code:%s price:%s"%(self.stock_code,self.stock_price) #在场景中,想要在网站A上查询股票
if __name__=="__main__":
web_a_query_dev=WebAStockQueryDevice()
web_a_query_dev.login("myStockA","myPwdA")
web_a_query_dev.setCode("")
web_a_query_dev.queryPrice()
web_a_query_dev.showPrice()
打印结果:
Web A:Login OK... user:myStockA pwd:myPwdA
Web A Querying...code:12345
Web A Stock Price...code:12345 price:20.0
但是发现每次操作,都会调用登录,设置代码,查询,展示这几步,是不是有些繁琐?既然有些繁琐,何不将这几步过程封装成一个接口。由于各个子类中的操作过程基本满足这个流程,所以这个方法可以写在父类中。
class StockQueryDevice():
stock_code=""
stock_price=0.0
def login(self,usr,pwd):
pass
def setCode(self,code):
self.stock_code=code
def queryPrice(self):
pass
def showPrice(self):
pass def operateQuery(self, usr, pwd, code):
if not self.login(usr, pwd):
return False
self.setCode(code)
self.queryPrice()
self.showPrice()
return True class WebAStockQueryDevice(StockQueryDevice):
def login(self,usr,pwd):
if usr=="myStockA" and pwd=="myPwdA":
print("Web A:Login OK... user:%s pwd:%s"%(usr,pwd))
return True
else:
print("Web A:Login ERROR... user:%s pwd:%s"%(usr,pwd))
return False
def queryPrice(self):
print("Web A Querying...code:%s "%self.stock_code)
self.stock_price=20.00
def showPrice(self):
print("Web A Stock Price...code:%s price:%s"%(self.stock_code,self.stock_price))
class WebBStockQueryDevice(StockQueryDevice):
def login(self,usr,pwd):
if usr=="myStockB" and pwd=="myPwdB":
print("Web B:Login OK... user:%s pwd:%s"%(usr,pwd))
return True
else:
print("Web B:Login ERROR... user:%s pwd:%s"%(usr,pwd))
return False
def queryPrice(self):
print("Web B Querying...code:%s "%self.stock_code)
self.stock_price=30.00
def showPrice(self):
print("Web B Stock Price...code:%s price:%s"%(self.stock_code,self.stock_price)) if __name__=="__main__":
web_a_query_dev=WebAStockQueryDevice()
web_a_query_dev.operateQuery("myStockA","myPwdA","")
打印结果相同:
Web A:Login OK... user:myStockA pwd:myPwdA
Web A Querying...code:12345
Web A Stock Price...code:12345 price:20.0
模式优点
在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序 。提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为。 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行 更换和增加新的子类很方便,符合单一职责原则和开闭原则
模式缺点
需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统会更加庞大,设计也会更加抽象(可结合桥接模式)
模式适用环境
一次性实现一个算法的不变部分,并将可变的行为留给子类来实现 。各子类中公共的行为应被提取出来,并集中到一个公共父类中,以避免代码重复。 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制
另外:
在模板方法模式中,子类不显式调用父类的方法,而是通过覆盖父类的方法来实现某些具体的业务逻辑,父类控制对子类的调用,这种机制被称为好莱坞原则(Hollywood Principle),好莱坞原则的定义为:“不要给我们打电话,我们会给你打电话(Don‘t call us, we’ll call you)”。在模板方法模式中,好莱坞原则体现在:子类不需要调用父类,而通过父类来调用子类,将某些步骤的实现写在子类中,由父类来控制整个过程。
python-模板方法模式的更多相关文章
- [python实现设计模式]-2.模板方法模式---把大象关进冰箱.
平时大家上班都很累,为了增加工作中的欢乐气氛,黄页组准备搞个游戏. 游戏的名字是把大象关进冰箱.游戏很简单,需要把指定的物品放进冰箱. 我们都知道,把大象放进冰箱,分3步. 第一步,打开冰箱门,第二步 ...
- 大话设计模式Python实现-模板方法模式
模板方法模式(Template Method Pattern):定义一个操作中的算法骨架,将一些步骤延迟至子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 下面是一个模 ...
- 简介Python设计模式中的代理模式与模板方法模式编程
简介Python设计模式中的代理模式与模板方法模式编程 这篇文章主要介绍了Python设计模式中的代理模式与模板方法模式编程,文中举了两个简单的代码片段来说明,需要的朋友可以参考下 代理模式 Prox ...
- Python笔记:设计模式之模板方法模式
此模式通过一个模板方法来定义程序的框架或算法,通常模板方法定义在基类中,即原始的模板,然后子类就可以根据不同的需要实现或重写模板方法中的某些算法步骤或者框架的某部分,最后达到使用相同模板实现不同功能的 ...
- python 设计模式之模板方法模式
1.模板方法模式定义 模板模式定义如下:定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定的步骤.子类实现的具体方法叫作基本方法,实现对 ...
- .NET责任链模式(混合单例模式,模板方法模式)-----制作与扩展能力验证
.NET责任链模式.单例模式.模板方法模式混用 前言 哇,看到题目挺长的,这个组合型的东西,到底能干啥呢?本篇文章来一起琢磨琢磨,这两天为了团队的软件赶工,我负责的那一块叫:插件管理器.我们团队的成员 ...
- 设计模式(九): 从醋溜土豆丝和清炒苦瓜中来学习"模板方法模式"(Template Method Pattern)
今天是五.四青年节,祝大家节日快乐.看着今天这标题就有食欲,夏天到了,醋溜土豆丝和清炒苦瓜适合夏天吃,好吃不上火.这两道菜大部分人都应该吃过,特别是醋溜土豆丝,作为“鲁菜”的代表作之一更是为大众所熟知 ...
- 设计模式(十四)模板方法模式(Template Pattern)
一.引言 提到模板,大家肯定不免想到生活中的“简历模板”.“论文模板”.“Word中模版文件”等,在现实生活中,模板的概念就是——有一个规定的格式,然后每个人都可以根据自己的需求或情况去更新它,例如简 ...
- C#设计模式-模板方法模式
提到模板,大家肯定不免想到生活中的“简历模板”.“论文模板”.“Word中模版文件”等,在现实生活中,模板的概念就是——有一个规定的格式,然后每个人都可以根据自己的需求或情况去更新它,例如简历模板,下 ...
- C#设计模式系列:模板方法模式(Template Method)
你去银行取款的时候,银行会给你一张取款单,这张取款单就是一个模板,它把公共的内容提取到模板中,只留下部分让用户来填写.在软件系统中,将多个类的共有内容提取到一个模板中的思想便是模板方法模式的思想. 模 ...
随机推荐
- Freemarker实例教程
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本人声明.否则将追究法律责任.作者:永恒の_☆ 地址:http://blog.csdn.net/chenghui0317/a ...
- 初识MQ
[参考文章]:到底什么时候该使用MQ? 1. 什么是MQ? 消息队列(Message Quene)是一种跨进程的通信机制,用于上下游传递消息. MQ是一种非常常见的上下游“逻辑解耦+物理解耦”的消息通 ...
- HTTP的请求报文与响应报文
报文: 简单来说,报文就是也就是HTTP报文,作用是在各个系统之间进行和响应时用来交换与传输的数据单元,即站点一次性要发送的数据块,这些数据块以一些文本形式的元信息开头,这些信息描述了报文的内容及含义 ...
- [原创]K8 CMS GoastGuard 密码解密工具
工具: K8 CMS GoastGuard PASS Decrypt编译: VS2012 C# (.NET Framework v4.5)组织: K8搞基大队[K8team]作者: K8拉登哥哥博客 ...
- 使用webpack和react搭建项目
看了N多博客,日志,一边迷茫一边摸索.本文记录流程.我怕自己忘了...并且修复了博客园首页推荐那个日志中遇到的bug 1.webstorm新建一个空白项目,比如webpack_demo 2.因为要用r ...
- 前端代码质量保障之代码review
经验丰富的程序员和一般程序员之间的最大区别,不仅体现在解决问题的能力上, 还体现在日常代码的风格上.掌握一门技术可能需要几月,甚至几周就够了. 好的习惯风格养成却需数年. 团队成员之间需要合作,代码需 ...
- [Error] 'exit' was not declared in this scope的解决方法
新手刚开始用Linux和c++写程序,可能会出现下面的错误 error: ‘exit’ was not declared in this scope 解决方法是 添加 #include <cst ...
- C# 多线程之List的线程安全问题
网上关于List的线程安全问题将的很少,所以自己实验了一把,发现确实是线程不安全的.所以当你在进行多线程编程中使用了共享的List集合,必须对其进行线程安全处理. List的Add方法是线程不安全的, ...
- 分布式锁的两种实现方式(基于redis和基于zookeeper)
先来说说什么是分布式锁,简单来说,分布式锁就是在分布式并发场景中,能够实现多节点的代码同步的一种机制.从实现角度来看,主要有两种方式:基于redis的方式和基于zookeeper的方式,下面分别简单介 ...
- 前端通信:ajax设计方案(五)--- 集成promise规范,更优雅的书写代码(改迭代已作废,移步迭代10)
该迭代已作废,最新的请移步这里:https://www.cnblogs.com/GerryOfZhong/p/10726306.html 距离上一篇博客书写,又过去了大概几个月了,这段时间暂时离开了这 ...