最近看了一下閻宏博士的《java與模式》,看的不多,的確很經典,通俗易懂,工作中很多的問題一下子就明朗了(本人菜鳥……)。
今天看到"工廠方法模式"(Factory Method)的一道思考題,其中又簡單涉及了"模板方法模式"(Template Method),原來工作中不懂的地方就是用的這樣的開發模式。書中的例子比較簡單,很容易理解,所以就敲了一下代碼,理解了一下。
題目的大意是:
現有兩個數據庫,假設是Mysql與Oracle兩個數據庫,要在Client客戶端上分別能查出兩個不同的數據庫的結果,通過工廠方法模式,設計一個合理的方案。
關於什么是工廠方法模式,書中給出的定義是:
工廠方法模式是類的創建模式,又叫做虛擬構造子模式或者多態性工廠模式。工廠方法模式的用意是定義一個創建產品對象的工廠接口,將實際創建工作推遲到子類中。
首先貼出他們之間關系的類圖:
代碼部分如下:
AbstractQueryRunner.java
1 import java.sql.Connection; 2 import java.sql.ResultSet; 3 4 public abstract class AbstractQueryRunner { 5 6 public ResultSet getResult(){ 7 Connection con = createConnection(); 8 String sql = createQueryString(); 9 return runSql(con,sql); 10 } 11 12 protected abstract Connection createConnection(); 13 protected abstract String createQueryString(); 14 protected abstract ResultSet runSql(Connection con,String sql); 15 }
AbstractQueryRunner的兩個子類,即操作兩個數據庫的類:
MysqlRunner.java
1 import java.sql.Connection; 2 import java.sql.ResultSet; 3 import java.sql.SQLException; 4 import java.sql.Statement; 5 6 public class MysqlRunner extends AbstractQueryRunner { 7 8 protected Connection createConnection(){ 9 //code here 10 return con; 11 } 12 13 @Override 14 protected String createQueryString() { 15 String queryString = "SELECT * FROM User"; 16 return queryString; 17 } 18 19 protected ResultSet runSql(Connection con,String sql){ 20 try { 21 Statement smt = con.createStatement(); 22 return smt.executeQuery(sql); 23 } catch (SQLException e) { 24 e.printStackTrace(); 25 return null; 26 } 27 } 28 }
OracleRunner.java
1 import java.sql.Connection; 2 import java.sql.ResultSet; 3 import java.sql.SQLException; 4 import java.sql.Statement; 5 6 public class OracleRunner extends AbstractQueryRunner { 7 8 protected Connection createConnection(){ 9 //code here 10 return con; 11 } 12 13 @Override 14 protected String createQueryString() { 15 String queryString = "SELECT * FROM User"; 16 return queryString; 17 } 18 19 protected ResultSet runSql(Connection con,String sql){ 20 try { 21 Statement smt = con.createStatement(); 22 return smt.executeQuery(sql); 23 } catch (SQLException e) { 24 e.printStackTrace(); 25 return null; 26 } 27 } 28 }
可以看到,兩個子類重寫了父類沒有具體實現的方法,這樣做的好處是子類可以任意寫自己內部的方法,是一種"開-閉原則"的體現。
客戶端代碼:
Client.java
1 import java.sql.ResultSet; 2 public class Client { 3 4 public static void main(String[] args) { 5 AbstractQueryRunner mRunner = new MysqlRunner(); 6 ResultSet result1 = mRunner.getResult(); 7 8 AbstractQueryRunner oRunner = new OracleRunner(); 9 ResultSet result2 = oRunner.getResult(); 10 } 11 12 }
這樣就能實現使用工廠方法模式在客戶端查詢不同的數據庫了。
總體使用了工廠方法模式,那模板方法模式體現在哪里呢,它就是其中的getResult()方法。關於模板方法模式的解釋,我翻閱了一下該書,它其中解釋的很詳細,現摘錄如下:
模板方法模式是類的行為模式。准備一個抽象類,將部分邏輯以具體方法以及具體構造子的形式實現,然后聲明一些抽象方法來迫使子類實現剩余的邏輯。不同的構造子類可以以不同的方法實現這些抽象方法,從而對剩余的邏輯有不同的實現。這就是模板方法模式的用意。