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

image.png
模板模式就是讓父類或者基類實現功能的代碼流程,而讓子類去實現差別內容;上述 UML 是描述模板模式的一個例子,具體看代碼吧。python

引自《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. 若是想定製差別化流程,則能夠在父類中實現一個方法,用於設置改變流程的變量,用這個變量控制分支流程,子類經過實現這個方法並靈活賦值,來改變模板流程流程。

下集預告 原型模式

相關文章
相關標籤/搜索