模板模式,作为常用的典型的代码复用技术,其同样是一种行为型的设计模式
模式思想 使用过JDBC来操作数据库的朋友,应该对那套操作流程非常熟悉:连接数据库、打开数据库、执行SQL语句、关闭数据库。但如果每次都写一大堆重复的代码而仅仅只是为了执行一个SQL语句,显然显得很啰嗦。而且事实上对于各种不同的数据库,比如MySQL、DB2、Oracle等等,基本的操作流程也是差不多的。历史经验告诉我们,重复的、冗余的代码具备可优化、可复用的潜能。这里为了复用上述场景的重复代码,我们来介绍一种新的设计模式——Template Pattern 模板模式
在模板模式下,其只有两个角色
抽象模板角色 :该角色中会定义若个抽象方法,以便让不同的具体模板角色去实现。与此同时,其还会提供一些具体方法,在该方法中其规定了若干个抽象方法调用的逻辑顺序,此方法即为所谓的模板方法 。可以看到,其是对之前代码中重复的调用逻辑的复用和组合。即本文的DatabaseTemplate数据库模板类
具体模板角色 :其是对抽象模板角色的具体实现。其提供了对抽象模板角色的抽象方法的具体实现。即本文的MySQL数据库模板MySQLTemplate类、DB2数据库模板DB2Template类、Oracle数据库模板OracleTemplate类
实现 现在通过Java来实现上面的例子。首先定义一个抽象模板角色,即DatabaseTemplate数据库模板类。可以看到其定义了操作各类型数据库的通用方法接口。与此同时还提供一个模板方法,其中规定了操作各数据库时的相关顺序逻辑。这里为了保证具体模板角色不对其进行重写,故使用了final进行修饰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public abstract class DatabaseTemplate { public final void useDatabase (String sql) { connectionDatabase(); openDatabase(); execSql(sql); closeDatabase(); } public abstract void connectionDatabase () ; public abstract void openDatabase () ; public abstract void execSql (String sql) ; public abstract void closeDatabase () ; }
现在,只需为各类型的数据库提供相应的具体模板类即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 public class MySQLTemplate extends DatabaseTemplate { @Override public void connectionDatabase () { System.out.println("连接 MySQL 数据库" ); } @Override public void openDatabase () { System.out.println("打开 MySQL 数据库" ); } @Override public void execSql (String sql) { System.out.println("执行SQL语句: " + sql); } @Override public void closeDatabase () { System.out.println("关闭 MySQL 数据库" ); } } ... public class DB2Template extends DatabaseTemplate { @Override public void connectionDatabase () { System.out.println("连接 DB2 数据库" ); } @Override public void openDatabase () { System.out.println("打开 DB2 数据库" ); } @Override public void execSql (String sql) { System.out.println("执行SQL语句: " + sql); } @Override public void closeDatabase () { System.out.println("关闭 DB2 数据库" ); } } ... public class OracleTemplate extends DatabaseTemplate { @Override public void connectionDatabase () { System.out.println("连接 Oracle 数据库" ); } @Override public void openDatabase () { System.out.println("打开 Oracle 数据库" ); } @Override public void execSql (String sql) { System.out.println("执行SQL语句: " + sql); } @Override public void closeDatabase () { System.out.println("关闭 Oracle 数据库" ); } }
现在,client操作各数据库时再也不写一大堆重复的代码了(连接数据库、打开数据库、执行SQL语句、关闭数据库)。而只需要获取相应的数据库模板实例进行操作即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class TemplatePatternDemo { public static void main (String[] args) { System.out.println("----------------- Test 1 -----------------" ); MySQLTemplate mySQLTemplate = new MySQLTemplate (); String sql1 = "drop table user_token" ; mySQLTemplate.useDatabase(sql1); System.out.println("\n----------------- Test 2 -----------------" ); DB2Template db2Template = new DB2Template (); String sql2 = "select * from user_info" ; db2Template.useDatabase(sql2); System.out.println("\n----------------- Test 3 -----------------" ); OracleTemplate oracleTemplate = new OracleTemplate (); String sql3 = "select * from system_log" ; oracleTemplate.useDatabase(sql3); } }
测试结果如下,符合预期
参考文献
Head First 设计模式 弗里曼著
图解设计模式 结城浩著