模板设计模式示例
本文是我們名為“ Java設(shè)計(jì)模式 ”的學(xué)院課程的一部分。
在本課程中,您將深入研究大量的設(shè)計(jì)模式,并了解如何在Java中實(shí)現(xiàn)和利用它們。 您將了解模式如此重要的原因,并了解何時(shí)以及如何應(yīng)用模式中的每一個(gè)。 在這里查看 !
目錄
1.簡介 2.什么是模板設(shè)計(jì)模式 3.實(shí)施模板設(shè)計(jì)模式 4.在模板內(nèi)部引入一個(gè)掛鉤 5.何時(shí)使用模板設(shè)計(jì)模式 6. JDK中的模板模式 7.下載源代碼1.簡介
模板設(shè)計(jì)模式是一種行為模式,顧名思義,它提供了供用戶使用的模板或算法結(jié)構(gòu)。 用戶無需改變算法的結(jié)構(gòu)即可提供自己的實(shí)現(xiàn)。
在問題的幫助下更容易理解這種模式。 我們將在本節(jié)中了解場景,并在下一節(jié)中使用Template模式實(shí)施解決方案。
您是否曾經(jīng)使用Java應(yīng)用程序連接到關(guān)系數(shù)據(jù)庫? 讓我們回想一下連接數(shù)據(jù)并將數(shù)據(jù)插入數(shù)據(jù)庫所需的一些重要步驟。 首先,根據(jù)要連接的數(shù)據(jù)庫,需要一個(gè)驅(qū)動程序。 然后,我們將一些憑據(jù)傳遞給數(shù)據(jù)庫,然后,準(zhǔn)備一條語句,將數(shù)據(jù)設(shè)置到insert語句中,然后使用insert命令將其插入。 稍后,我們關(guān)閉所有連接,并有選擇地銷毀所有連接對象。
無論任何供應(yīng)商的關(guān)系數(shù)據(jù)庫,您都需要編寫所有這些步驟。 考慮一個(gè)問題,您需要將一些數(shù)據(jù)插入不同的數(shù)據(jù)庫。 您需要從CSV文件中獲取一些數(shù)據(jù),然后將其插入MySQL數(shù)據(jù)庫中。 一些數(shù)據(jù)來自文本文件,應(yīng)將其插入Oracle數(shù)據(jù)庫中。 唯一的區(qū)別是驅(qū)動程序和數(shù)據(jù),其余步驟應(yīng)該相同,因?yàn)镴DBC提供了一組通用的接口來與任何供應(yīng)商的特定關(guān)系數(shù)據(jù)庫進(jìn)行通信。
我們可以創(chuàng)建一個(gè)模板,該模板將為客戶端執(zhí)行一些步驟,并留下一些步驟讓客戶端以自己的特定方式實(shí)現(xiàn)它們。 (可選)客戶端可以覆蓋某些已定義步驟的默認(rèn)行為。
現(xiàn)在,在實(shí)現(xiàn)代碼之前,讓我們進(jìn)一步了解模板設(shè)計(jì)模式。
2.什么是模板設(shè)計(jì)模式
模板模式定義了操作中算法的框架,將某些步驟推遲到子類。 模板方法允許子類在不更改算法結(jié)構(gòu)的情況下重新定義算法的某些步驟。
模板方法模式可以在存在算法的情況下使用,其中某些步驟可以以多種不同方式實(shí)現(xiàn)。 在這種情況下,模板方法模式建議將算法的大綱保留在一個(gè)類(稱為模板類)內(nèi)的稱為模板方法的單獨(dú)方法中,而忽略變體部分的具體實(shí)現(xiàn)(步驟該算法可以針對此類的不同子類以多種不同方式實(shí)現(xiàn))。
Template類不一定必須將實(shí)現(xiàn)全部留給子類。 而是,作為提供算法概述的一部分,Template類還可以提供一定數(shù)量的實(shí)現(xiàn),這些實(shí)現(xiàn)可以視為在不同實(shí)現(xiàn)之間是不變的。 如果合適,它甚至可以為變體部件提供默認(rèn)實(shí)現(xiàn)。 在不同的子類中將僅實(shí)現(xiàn)特定的細(xì)節(jié)。 這種實(shí)現(xiàn)方式消除了對重復(fù)代碼的需求,這意味著要編寫的代碼量最少。
圖1
抽象類
- 定義具體的子類定義的抽象基本操作,以實(shí)現(xiàn)算法的步驟。
- 實(shí)現(xiàn)定義算法框架的模板方法。 模板方法調(diào)用原始操作以及在AbstractClass定義的操作或其他對象的操作。
ConcreteClass - 實(shí)現(xiàn)原始操作進(jìn)行。
3.實(shí)施模板設(shè)計(jì)模式
在下面,我們可以看到連接模板類,該類用于為客戶端提供一個(gè)用于連接各種數(shù)據(jù)庫并與之通信的模板。
package com.javacodegeeks.patterns.templatepattern;public abstract class ConnectionTemplate {public final void run() {setDBDriver();setCredentials();connect();prepareStatement();setData();insert();close();destroy();}public abstract void setDBDriver();public abstract void setCredentials();public void connect() {System.out.println("Setting connection...");}public void prepareStatement() {System.out.println("Preparing insert statement...");}public abstract void setData();public void insert() {System.out.println("Inserting data...");}public void close() {System.out.println("Closing connections...");}public void destroy() {System.out.println("Destroying connection objects...");} }抽象類提供了連接,通信以及稍后關(guān)閉連接的步驟。 必須完成所有這些步驟才能完成工作。 該類為某些常見步驟提供了默認(rèn)實(shí)現(xiàn),并將特定步驟保留為抽象,從而迫使客戶端為其提供實(shí)現(xiàn)。
用戶應(yīng)該實(shí)現(xiàn)setDBDriver方法以提供特定于數(shù)據(jù)庫的驅(qū)動程序。 對于不同的數(shù)據(jù)庫,憑據(jù)可能不同; 因此, setCredentials也保留為抽象狀態(tài),以使用戶可以實(shí)現(xiàn)它。
同樣,使用JDBC API連接到數(shù)據(jù)庫并準(zhǔn)備語句是很常見的。 但是,數(shù)據(jù)將是特定的,因此用戶將提供它,而其他步驟(如運(yùn)行插入語句,關(guān)閉連接和銷毀對象)則與任何數(shù)據(jù)庫相似,因此它們的實(shí)現(xiàn)在模板內(nèi)保持通用。
上一類的關(guān)鍵方法是run方法。 run方法用于按順序運(yùn)行這些步驟。 該方法被設(shè)置為最終方法,因?yàn)檫@些步驟應(yīng)保持安全,并且任何用戶都不得更改。
下面的兩個(gè)類擴(kuò)展了模板類,并為某些方法提供了特定的實(shí)現(xiàn)。
package com.javacodegeeks.patterns.templatepattern;public class MySqLCSVCon extends ConnectionTemplate {@Overridepublic void setDBDriver() {System.out.println("Setting MySQL DB drivers...");}@Overridepublic void setCredentials() {System.out.println("Setting credentials for MySQL DB...");}@Overridepublic void setData() {System.out.println("Setting up data from csv file....");} }上面的類用于連接到MySQL數(shù)據(jù)庫,并通過讀取CSV文件提供數(shù)據(jù)。
package com.javacodegeeks.patterns.templatepattern;public class OracleTxtCon extends ConnectionTemplate {@Overridepublic void setDBDriver() {System.out.println("Setting Oracle DB drivers...");}@Overridepublic void setCredentials() {System.out.println("Setting credentials for Oracle DB...");}@Overridepublic void setData() {System.out.println("Setting up data from txt file....");} }上面的類用于連接到Oracle數(shù)據(jù)庫,并通過讀取文本文件來提供數(shù)據(jù)。
現(xiàn)在,讓我們測試代碼。
package com.javacodegeeks.patterns.templatepattern;public class TestTemplatePattern {public static void main(String[] args) {System.out.println("For MYSQL....");ConnectionTemplate template = new MySqLCSVCon();template.run();System.out.println("For Oracle...");template = new OracleTxtCon();template.run();} }上面的代碼將導(dǎo)致以下輸出:
For MYSQL.... Setting MySQL DB drivers... Setting credentials for MySQL DB... Setting connection... Preparing insert statement... Setting up data from csv file.... Inserting data... Closing connections... Destroying connection objects... For Oracle... Setting Oracle DB drivers... Setting credentials for Oracle DB... Setting connection... Preparing insert statement... Setting up data from txt file.... Inserting data... Closing connections... Destroying connection objects...上面的輸出清楚地顯示了模板模式如何使用類似的方式與不同的數(shù)據(jù)庫連接和通信。 該模式將通用代碼保留在一個(gè)類下,并提高了代碼的可重用性。 它為用戶設(shè)置了一個(gè)框架并對其進(jìn)行控制,并允許用戶擴(kuò)展模板,以便為某些步驟提供特定的實(shí)現(xiàn)。
現(xiàn)在,如果我們通過添加日志記錄機(jī)制來增強(qiáng)上述示例。 但是代碼的某些用戶不想添加此功能,要實(shí)現(xiàn)此功能,我們可以使用鉤子。 掛鉤是模板類內(nèi)部具有默認(rèn)行為的簡單方法; 此行為可用于更改一些可選步驟。 用戶應(yīng)實(shí)現(xiàn)此方法,該方法可以掛接到模板類內(nèi)部以更改算法的可選步驟。
4.在模板內(nèi)部引入一個(gè)掛鉤
讓我們用鉤子增強(qiáng)上面的示例。
package com.javacodegeeks.patterns.templatepattern;import java.util.Date;public abstract class ConnectionTemplate {private boolean isLoggingEnable = true;public ConnectionTemplate() {isLoggingEnable = disableLogging();}public final void run() {setDBDriver();logging("Drivers set [" + new Date() + "]");setCredentials();logging("Credentails set [" + new Date() + "]");connect();logging("Conencted");prepareStatement();logging("Statement prepared [" + new Date() + "]");setData();logging("Data set [" + new Date() + "]");insert();logging("Inserted [" + new Date() + "]");close();logging("Conenctions closed [" + new Date() + "]");destroy();logging("Object destoryed [" + new Date() + "]");}public abstract void setDBDriver();public abstract void setCredentials();public void connect() {System.out.println("Setting connection...");}public void prepareStatement() {System.out.println("Preparing insert statement...");}public abstract void setData();public void insert() {System.out.println("Inserting data...");}public void close() {System.out.println("Closing connections...");}public void destroy() {System.out.println("Destroying connection objects...");}public boolean disableLogging() {return true;}private void logging(String msg) {if (isLoggingEnable) {System.out.println("Logging....: " + msg);}} }我們在上述模板類中引入了兩個(gè)新方法。 disableLogging是一個(gè)返回boolean的鉤子。 默認(rèn)情況下,啟用日志記錄的布爾值isLoggingEnable為true。 如果應(yīng)該為他的代碼禁用日志記錄,則用戶可以覆蓋此方法。 另一種是用于記錄消息的私有方法。
下面的類實(shí)現(xiàn)了hook方法并返回false,從而關(guān)閉了此特定工作的日志記錄機(jī)制。
package com.javacodegeeks.patterns.templatepattern;public class MySqLCSVCon extends ConnectionTemplate {@Overridepublic void setDBDriver() {System.out.println("Setting MySQL DB drivers...");}@Overridepublic void setCredentials() {System.out.println("Setting credentials for MySQL DB...");}@Overridepublic void setData() {System.out.println("Setting up data from csv file....");}@Overridepublic boolean disableLogging() {return false;} }讓我們測試一下這段代碼。
package com.javacodegeeks.patterns.templatepattern;public class TestTemplatePattern {public static void main(String[] args) {System.out.println("For MYSQL....");ConnectionTemplate template = new MySqLCSVCon();template.run();System.out.println("For Oracle...");template = new OracleTxtCon();template.run();} }上面的類將導(dǎo)致以下輸出:
For MYSQL.... Setting MySQL DB drivers... Setting credentials for MySQL DB... Setting connection... Preparing insert statement... Setting up data from csv file.... Inserting data... Closing connections... Destroying connection objects... For Oracle... Setting Oracle DB drivers... Logging....: Drivers set [Sat Nov 08 23:53:47 IST 2014] Setting credentials for Oracle DB... Logging....: Credentails set [Sat Nov 08 23:53:47 IST 2014] Setting connection... Logging....: Conencted Preparing insert statement... Logging....: Statement prepared [Sat Nov 08 23:53:47 IST 2014] Setting up data from txt file.... Logging....: Data set [Sat Nov 08 23:53:47 IST 2014] Inserting data... Logging....: Inserted [Sat Nov 08 23:53:47 IST 2014] Closing connections... Logging....: Conenctions closed [Sat Nov 08 23:53:47 IST 2014] Destroying connection objects... Logging....: Object destoryed [Sat Nov 08 23:53:47 IST 2014]您可以在輸出中清楚地看到,對于MySQL實(shí)現(xiàn),日志記錄已關(guān)閉,而對于Oracle實(shí)現(xiàn),日志記錄已關(guān)閉。
5.何時(shí)使用模板設(shè)計(jì)模式
在以下情況下應(yīng)使用模板方法模式:
- 一次實(shí)現(xiàn)算法的不變部分,然后將其留給子類來實(shí)現(xiàn)可以變化的行為。
- 子類之間的共同行為應(yīng)分解并集中在一個(gè)共同類中,以避免代碼重復(fù)。 您首先要確定現(xiàn)有代碼中的差異,然后將差異分為新的操作。 最后,將不同的代碼替換為調(diào)用這些新操作之一的模板方法。
- 控制子類擴(kuò)展。 您可以定義一個(gè)模板方法,該方法在特定點(diǎn)調(diào)用“掛鉤”操作(請參閱結(jié)果),從而僅允許在這些點(diǎn)進(jìn)行擴(kuò)展。
6. JDK中的模板模式
- java.util.Collections#sort()
- java.io.InputStream#skip()
- java.io.InputStream#read()
- java.util.AbstractList#indexOf()
7.下載源代碼
這是有關(guān)模板設(shè)計(jì)模式的課程。 您可以在此處下載源代碼: TemplatePattern-Project
翻譯自: https://www.javacodegeeks.com/2015/09/template-design-pattern.html
總結(jié)
- 上一篇: http invoker_Http In
- 下一篇: 口袋忍者电脑版(忍者大乱斗口袋版官网)