python模板模式_python-模板方法模式

说明:

模板方法模式时行为模式中比较简单的设计模式之一。模板方法关注这样的一类行为:该类行为在执行过程中拥有大致相同的动作次序,只是动作在实现的具体细节上有所差异。例如:泡茶和泡咖啡,泡茶:把水煮沸,沸水加入茶叶,把倒进杯子。泡咖啡:把水煮沸,用沸水冲咖啡粉,把咖啡倒进杯子。这样看来泡茶和泡咖啡的三个步骤基本相似。我们可以报这一类行为抽象成一个算法,并将其中的动作序列按1其先后顺序也抽象出来作为该算法的一些步骤。至于这些步骤的实现细节,则有算法的子类去实现。

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

模板方法模式 是一种基于继承的代码复用技术 ,将一些复杂流程的实现步骤封装在一系列基本方法中 ,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。

1367382-20180603174828178-863836673.png

模板方法模式的结构

模板方法模式包含以下两个角色: AbstractClass(抽象类) ConcreteClass(具体子类)

模板方法模式的实现:

模板方法 (Template Method)

基本方法 (Primitive Method) :1、抽象方法(Abstract Method)2、 具体方法(Concrete Method) 3、钩子方法(Hook Method) :“挂钩”方法和空方法

实例:

投资股票是种常见的理财方式,我国股民越来越多,实时查询股票的需求也越来越大。今天,我们通过一个简单的股票查询客户端来认识一种简单的设计模式:模板模式。

根据股票代码来查询股价分为如下几个步骤:登录、设置股票代码、查询、展示。

#构造如下的虚拟股票查询器:

classStockQueryDevice():

stock_code="0"stock_price=0.0

deflogin(self,usr,pwd):pass

defsetCode(self,code):

self.stock_code=codedefqueryPrice(self):pass

defshowPrice(self):pass

#根据不同的查询机构和方式来通过继承的方式实现其的股票查询器类。#WebA和WebB的查询器类可以构造如下:

classWebAStockQueryDevice(StockQueryDevice):deflogin(self,usr,pwd):if usr=="myStockA" and pwd=="myPwdA":print "Web A:Login OK... user:%s pwd:%s"%(usr,pwd)returnTrueelse:print "Web A:Login ERROR... user:%s pwd:%s"%(usr,pwd)returnFalsedefqueryPrice(self):print "Web A Querying...code:%s"%self.stock_code

self.stock_price=20.00

defshowPrice(self):print "Web A Stock Price...code:%s price:%s"%(self.stock_code,self.stock_price)classWebBStockQueryDevice(StockQueryDevice):deflogin(self,usr,pwd):if usr=="myStockB" and pwd=="myPwdB":print "Web B:Login OK... user:%s pwd:%s"%(usr,pwd)returnTrueelse:print "Web B:Login ERROR... user:%s pwd:%s"%(usr,pwd)returnFalsedefqueryPrice(self):print "Web B Querying...code:%s"%self.stock_code

self.stock_price=30.00

defshowPrice(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("12345")

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

但是发现每次操作,都会调用登录,设置代码,查询,展示这几步,是不是有些繁琐?既然有些繁琐,何不将这几步过程封装成一个接口。由于各个子类中的操作过程基本满足这个流程,所以这个方法可以写在父类中。

classStockQueryDevice():

stock_code="0"stock_price=0.0

deflogin(self,usr,pwd):pass

defsetCode(self,code):

self.stock_code=codedefqueryPrice(self):pass

defshowPrice(self):pass

defoperateQuery(self, usr, pwd, code):if notself.login(usr, pwd):returnFalse

self.setCode(code)

self.queryPrice()

self.showPrice()returnTrueclassWebAStockQueryDevice(StockQueryDevice):deflogin(self,usr,pwd):if usr=="myStockA" and pwd=="myPwdA":print("Web A:Login OK... user:%s pwd:%s"%(usr,pwd))returnTrueelse:print("Web A:Login ERROR... user:%s pwd:%s"%(usr,pwd))returnFalsedefqueryPrice(self):print("Web A Querying...code:%s"%self.stock_code)

self.stock_price=20.00

defshowPrice(self):print("Web A Stock Price...code:%s price:%s"%(self.stock_code,self.stock_price))classWebBStockQueryDevice(StockQueryDevice):deflogin(self,usr,pwd):if usr=="myStockB" and pwd=="myPwdB":print("Web B:Login OK... user:%s pwd:%s"%(usr,pwd))returnTrueelse:print("Web B:Login ERROR... user:%s pwd:%s"%(usr,pwd))returnFalsedefqueryPrice(self):print("Web B Querying...code:%s"%self.stock_code)

self.stock_price=30.00

defshowPrice(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","12345")

打印结果相同:

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)”。在模板方法模式中,好莱坞原则体现在:子类不需要调用父类,而通过父类来调用子类,将某些步骤的实现写在子类中,由父类来控制整个过程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/329870.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nacos启动失败:org.springframework.boot.web.server.WebServerExceptio

准备环境 系统环境: windows nacos: 2.0.0-BETA 错误信息 org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat 配置文件…

post使用form-data和x-www-form-urlencoded的本质区别

转自: post使用form-data和x-www-form-urlencoded的本质区别_null-CSDN博客一是数据包格式的区别,二是数据包中非ANSCII字符怎么编码,是百分号转码发送还是直接发送一、application/x-www-form-urlencoded1、它是post的默认格式,…

使用Nancy打造TaskManager2.0管理系统

上一篇开源任务管理平台TaskManager介绍发布后,有网友联系我看看能不能做个后台管理界面,方便管理系统中所有的任务。由于时间和技术问题1.0版本的时候,新增了一个3分钟读取配置文件动态修改任务的功能,不过总体来说还是不直观&am…

Java对象的序列化与反序列化

转载自 Java对象的序列化与反序列化 序列化与反序列化 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。一般将一个对象存储至一个储存媒介,例如档案或是记亿体缓冲等。在网络传输过程中,可以是字节或是XML等格式。而字节的…

网站能拿到其他网站的cookie_网站能给公司带来哪些好处?

事实上,许多企业仍在努力建立一个网站,因为如果它建立起来,它需要一笔钱和其他费用。但此时客户业务不太好,企业客户需要考虑很多问题,但创建网站的企业已经尝到了甜头。其实有些朋友可能会有一些偏差。例如&#xff0…

笨办法学习@ConditionalOnProperty 烧脑配置记录

前言 今天继续学习springboot时,一不小心就被ConditionalOnProperty注解的配置真假搞得我真的变得真真假假了。。(此为真,彼为假,到底你是真还是你是假,晕了晕了。。。) 本片主要记录一下注解的真假情况 …

javaI/O流小结

【README】 1.本文总结java IO读取或写入数据的方式和相关类说明; 2.java IO建立在流之上的。输入流读取数据,输出流写入数据; 3.过滤器流-filter stream,可以串连(修饰)到输入流和输出流上;…

送给微软中文.NET社区的一份礼物,.NET FM

自报家门 大家好,我是.NET FM。做为一档专业而轻松的播客节目,在今后的日子里,我将为你奉上有关.NET和微软公司其他技术的新鲜资讯(偷偷讲下,还有各种八卦哦)。 Lex Li的回忆 认识吕鹏同学真的是非常偶然…

你真的以为你了解Java的序列化了吗

转载自 你真的以为你了解Java的序列化了吗 上一篇文章《Java对象的序列化与反序列化》中,简单介绍了Java中对象的序列化和反序列化的一些基础知识。看文那篇文章后,有小伙伴留言说:我终于了解了Java的序列化了。我只想说:小伙子&a…

SpringBoot配置mybatis-mysql数据源

前言 学习SpringBoot整合mybatis mysql配置,首先需要了解什么是ORM(对象映射关系)框架,ORM(Object Relational Mapping)对象关系映射,是 一种为了解决面向对象与关系型数据库不匹配而出现的技术,使开发者…

编程猜单词游戏python_Python实现简单的猜单词小游戏

本文实例为大家分享了Python实现猜单词小游戏的具体代码,供大家参考,具体内容如下 思路 1、一个words列表里存放若干的单词,例如:["extends", "private", "static", "public"]2、在words…

java URL和URI

【README】 本文阐述了 URL, URI,以及对应的java类的api; 1.URI,统一资源标识符,标识互联网上的某个网络资源,标识方式如 名称,位置等;就像人的标识一样,可以通过身份证…

HoloLens开发手记-全息Hologram

全息 Hologram HoloLens使我们可以通过周边世界的光线和声音来创建全息场景和物体,使得它们像真实物体那样。全息场景能够响应你的凝视、手势和语音指令,同时还会和你周边世界的表面交互。借助全息场景,你可以在周边世界创建数码物体。 class…

全网把Map中的hash()分析的最透彻的文章,别无二家。

转载自 全网把Map中的hash()分析的最透彻的文章,别无二家。你知道HashMap中hash方法的具体实现吗? 你知道HashTable、ConcurrentHashMap中hash方法的实现以及原因吗? 你知道为什么要这么实现吗? 你知道为什么JDK 7和JDK 8中hash方…

python下面的代码_解析一下下面的python代码?

class Model(dict, metaclassModelMetaclass): # 初始化, 没啥好说的 def __init__(self, **kw): super(Model, self).__init__(**kw) # 如果取不到值, 报错, 这是一个魔术方法, 使用时直接getattr(obj, key) def __getattr__(self, key): try: return self[key] except KeyErr…

SpringBoot多数据源(主从数据源)配置

🎶前言 学习springboot配置多数据源,先回顾一下springboot配置单数据源的方式 SpringBoot配置mybatis-mysql数据源 🔠主从数据源搭建 项目依赖 本次记录多数据源配置主要是通过druid mybatis plus aop的形式实现的,mybatis …

(转)HttpURLConnection与 HttpClient 区别

转自: HttpURLConnection与 HttpClient 区别/性能测试对比 - 尚码园HttpURLConnection与HttpClient随笔   目前在工做中遇到的须要各类对接接口的工做,须要用到HTTP的知识,工做完成后想要作一些笔记,原本知识打算把本身写的代码…

Raspkate - 基于.NET的可运行于树莓派的轻量型Web服务器

最近在业余时间玩玩树莓派,刚开始的时候在树莓派里写一些基于wiringPi库的C语言程序来控制树莓派的GPIO引脚,从而控制LED发光二极管的闪烁,后来觉得,是不是可以使用HTML5jQuery等流行的前端技术做一个简单的Web站点,让…

深入分析Java中的length和length()

转载自 深入分析Java中的length和length()在开始正文之前,请你快速回答如下问题:在不使用任何带有自动补全功能IDE的情况下,如何获取一个数组的长度?以及,如何获取一个字符串的长度?这个问题我问过不同水平…

归并排序示例

public class MergeSortMain {public static void main(String[] args) {int[] arr {5, 4, 6, 2, 3, 7, 9, 1, 8};sort(arr);print(arr);}static void sort(int[] arr) {sort(arr, 0, arr.length - 1);}/*** param arr 数组* param leftBound 左边界* param rightBoun…