最近看了一下阎宏博士的《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()方法。关于模板方法模式的解释,我翻阅了一下该书,它其中解释的很详细,现摘录如下:
模板方法模式是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的构造子类可以以不同的方法实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意。