Neil 啃设计模式(0x05)模板模式

模板模式(Template Pattern)

定义

Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.(定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
《设计模式之禅》
模板模式最主要的目的就是简化代码冗余,将相同的执行流程,模板化。

UML 示例

@startuml
Abstract QueryTemplate
class NewVehiclesQuery
class UserGrossQuery

QueryTemplate <|-- NewVehiclesQuery
QueryTemplate <|-- UserGrossQuery
@enduml

Neil 啃设计模式(0x05)模板模式_第1张图片
模板模式就是让父类或者基类实现功能的代码流程,而让子类去实现差异内容;上述 UML 是描述模板模式的一个例子,具体看代码吧。

引自《python3》面向对象编程

代码实现

# 创建数据库基础信息
import sqlite3


conn = sqlite3.connect('sales.db')
conn.execute("CREATE TABLE Sales (salesperson text, amt currency, year integer, model text, new boolean)")
conn.execute("INSERT INTO Sales values ('Tim', 16000, 2010, 'Honda Fit', 'true')")
conn.execute("INSERT INTO Sales values ('Tim', 9000, 2006, 'Ford Focus', 'false')")
conn.execute("INSERT INTO Sales values ('Gayle', 8000, 2004, 'Dodge Neon', 'false')")
conn.execute("INSERT INTO Sales values ('Gayle', 28000, 2009, 'Ford Mustang', 'true')")
conn.execute("INSERT INTO Sales values ('Gayle', 50000, 2010, 'Lincoln Navigator', 'true')")
conn.execute("INSERT INTO Sales values ('Don', 20000, 2008, 'Toyota Prius', 'false')")
conn.commit()
conn.close()
# 模板模式举例
import datetime
import sqlite3


class QueryTemplate:
    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()

    # 作为模板代码,公共部分
    def process_format(self):
        self.connect()
        self.construct_query()
        self.do_query()
        self.format_results()
        self.output_results()


class NewVehicleQuery(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)


if __name__ == "__main__":
    query1 = NewVehicleQuery()
    query1.process_format()

    query2 = UserGrossQuery()
    query2.process_format()

知识点

  1. 模板模式相对简单主要用于让父类实现公共逻辑部分,而子类实现差异化代码
  2. python 中如果想要让子类必须实现某个方法,则可以使用 raise NotImplementedError()方式,如果子类没有实现则会调用父类方法从而抛出异常,如果使用 pass 则不会报错,导致问题被掩盖无法定位
  3. sqlite3 是 python 自带的标准库,可以作为 demo 实现时使用
  4. 如果想定制差异化流程,则可以在父类中实现一个方法,用于设置改变流程的变量,用这个变量控制分支流程,子类通过实现这个方法并灵活赋值,来改变模板流程流程。

下集预告 原型模式

你可能感兴趣的:(python,uml,设计模式)