美文网首页
模板模式

模板模式

作者: 井底蛙蛙呱呱呱 | 来源:发表于2019-04-14 16:16 被阅读0次
模板模式有助于去除重复代码。我们有不同的任务需求需要完成,但是这些任务中的一些步骤相同。共同的步骤在积累中被执行,而不同的步骤会在子类中被重写以提供自定义的行为。除了使用基类共享算法相似的部分,在一些方面,它就如同一个通用的策略模式。下面是模板模式在UML中的表现形式:

模板实例

让我们创建一个汽车销售报告单作为例子。我们能在SQLite数据库表中储存销售记录。SQLite是一个基于文件的简单数据引擎,它允许我们是用SQL语法来储存记录。Python3 将SQLite包含在其标准库中。

现在我们需要执行两个常见的任务:

  • 选择所有销售的新车并以逗号分隔的格式输出到屏幕上;
  • 输出一个以逗号分隔的包含所有销售人员和他们销售总额的列表,并且将其保存到一个可以导入到电子表格的文件当中。

这看起来是两个很不相同的任务,但是他们有一些共同的特征。在这两个任务中,我们都需要执行如下步骤:

    1. 连接数据库;
    1. 构造一个查询新车或销售总额的查询函数;
    1. 发出查询请求;
    1. 将结果格式化为一个以逗号分隔的字符串;
    1. 输出数据到一个或电子邮件中。

这两个任务查询函数的构建和输出步骤是不同的,但是它们的其他步骤是相同的。我们可以使用模板模式将相同步骤放在一个基类中,而将不同步骤放在两个子类中。

在开始之前,我们构建一个数据库,把一些示例数据放进去:

在这里我们已经创建了一个表来保存数据,并使用了6个插入语句来添加销售记录。数据储存在一个名为sales.db的文件中。现在数据样本创建好了。

接着我们根据上面列出的任务步骤,我们就从定义包含着些步骤的基类开始。每一个步骤都有自己的方法(使它很容易有选择的重写任何一步),我们有一个更加普遍的方法叫作依次调用步骤。对于我们的例子来说,我们的两个雷之间有3个方法是相同的:

import sqlite3

class QueryTemplate(object):
    def connect(self):
        self.conn = sqlite3.connect('sales.db')
    
    def construct_query(self):
        raise NotImplementedError
    
    def do_query(self):
        results = self.conn.execute(self.query)
        self.results = results.fetchall()
    
    def format_results(self):
        output = []
        for row in self.results:
            row = [str(i) for i in row]
            output.append(", ").join(row)
        self.formatted_results = "\n".join(output)
        
    def output_results(self):
        raise NotImplementedError

为帮助之类的实现,另外两个没有指定内容的方法会提示NotImplementedError。在python中,这是一个指定抽象接口的常见方式。这种方法可以不包含任何实现(使用pass),甚至可以完全不指定。然而,提示NotImplementedError可以帮助程序员理解,这个方法是需要被子类重写的;当我们忘记实现这些方法时,一个空白或者是不存在的方法会使得我们在试图实现他们的时候很难鉴别和排错。

现在我们有了一个模板可以处理这些无聊的细节,但是它也是足够灵活的,能够允许各种各样的查询方式来对他进行执行和格式化。最棒的部分在于,如果我们想要将我们的SQLite数据库引擎变成另一种数据库引擎,只需要改变模板类就行了,不需要去改编子类。

现在,让我们来实现两个具体的子类:

import datetime

class NewVehiclesQuery(QueryTemplate):
    def construct_query(self):
        self.query = "select * from Sales where new='true'"
    
    def output_results(self):
        print(self.format_results)

class UserGrossQuery(QueryTemplate):
    def construct_query(self):
        self.query = ("select salesperson, sum(amt) "+ 
                     " from Sales group by salesperson")
    
    def output_results(self):
        filename = "gross_sales_{0}".format(
            datetime.date.today().strftime("%Y%m%d"))
        with open(filename, 'w') as outfile:
            outfile.write(self.formatted_results)

这两个类实际上都是相当短的,思考一下他们所做的工作:连接到一个数据库,执行一个查询,格式化结果并输出。这个超类可以负责处理重复性的工作,但也可以很容易地让我们区分这些任务之间的不同步骤。更进一步,我们也可以很容易地改进基类提供的步骤。例如,如果我们想要输出一个格式有别于逗号分隔的字符串(例如,将一个HTML报告上传到一个网站上),我们依然可以重写format_results。

参考:
《Python3 面向对象编程》

相关文章

  • 11.8设计模式-模板模式-详解

    设计模式-模式模式 模板方法模式详解 模板方法模式在android中的实际运用 1.模板方法模式详解 2.模板方法...

  • 第5章 -行为型模式-模板方法模式

    一、模板方法模式的简介 二、模板方法模式的优点 三、模板方法模式的应用场景 四、模板方法模式的实例

  • 模板方法模式

    模板方法模式 模板方法模式的定义 模板方法模式(Template Method Pattern)是如此简单,以致让...

  • 设计模式系列-模板方法模式

    JAVA设计模式系列: 单例模式 观察者模式 模板方法模式 模板方法模式 定义 模板方法模式在一个方法中定义了算法...

  • 设计模式(行为型)-- 模板模式

    模板模式的原理与实现 模板模式,全称是模板方法设计模式,英文是 Template Method Design Pa...

  • 行为型-Template

    模板模式的原理与实现 模板模式,全称是模板方法设计模式,英文是 Template Method Design Pa...

  • 行为型 模板模式(文末有项目连接)

    1:模板方式解决的问题(先了解) 2:模板模式的原理与实现 3:模板模式核心代码 4:模板模式复用例子(Input...

  • 模板模式,也是解耦算法的吗?

    模板模式,和算法有什么关系呢? 模板模式,在什么场景使用呢? 模板模式(Template Pattern),定义一...

  • 模板方法模式

    一、模板方法模式介绍 二、模板方法模式代码实例

  • 58 - 模板模式

    本文来学习另外一种行为型设计模式,模板模式。模板模式主要是用来解决复用和扩展两个问题 模板模式的原理与实现 模板模...

网友评论

      本文标题:模板模式

      本文链接:https://www.haomeiwen.com/subject/dsqswqtx.html