設計模式——模板模式
所謂模板,當然是一個通用的模型,他要把一成不變的事物提取出來,之后在其中加入個性的操作,來完成我們的需求。恰當的在程序設計中使用模板模式能夠大大的縮短開發周期及代碼量,這樣一來,既能保證程序中各個模塊的規范統一,又能減少BUG。學習設計模式一定通過實例來驅動,spring和JDBC的整合就可以看到模板模式的身影
一般來說,使用JDBC操作數據庫無非以下幾個步驟
1,創建數據源并獲取連接
2,通過連接創建預定義的查詢
3,設定查詢的參數
4,新建結果集接收查詢返回的結果
而這些步驟中,1和4是每一次操作所必須的,而2和3才是開發者需要自定義的,spring抽取了這些公共的操作,把自定義操作通過接口暴露給開發者,恰當的運用了模板模式。
拿出一個spring整合JDBC中UserDao的例子,撇開整合的過程,單看jdbcTemplate,我們給jdbcTemplate傳入SQL語句和指定的參數,就完成了對數據庫的更新,公共的操作我們則不需要去擔心
1 @Repository("userJdbcDao")
2 public class UserDao implements IUserDao {
3
4 private JdbcTemplate jdbcTemplate;
5
6 //在此注入datasource創建jdbcTemplate
7 @Resource
8 public void setDataSource(DataSource dataSource) {
9 this.jdbcTemplate = new JdbcTemplate(dataSource);
10 }
11
12 /**
13 * 更新
14 */
15 public void update(User user) {
16 jdbcTemplate.update("update t_user set name = ? where id = ?",
17 user.getName(), user.getId());
18 }
19 }
模擬spring模板的功能,通過繼承的方式來實現一個模板,自定義一個模板2 public class UserDao implements IUserDao {
3
4 private JdbcTemplate jdbcTemplate;
5
6 //在此注入datasource創建jdbcTemplate
7 @Resource
8 public void setDataSource(DataSource dataSource) {
9 this.jdbcTemplate = new JdbcTemplate(dataSource);
10 }
11
12 /**
13 * 更新
14 */
15 public void update(User user) {
16 jdbcTemplate.update("update t_user set name = ? where id = ?",
17 user.getName(), user.getId());
18 }
19 }
1 package org.duyt.template;
2
3 public abstract class JdbcTemplateByInherit {
4 /**
5 * 公共操作:開啟連接
6 */
7 private void beginCon(){
8 System.out.println("開啟連接");
9 }
10 /**
11 * 公共操作:關閉連接
12 */
13 private void closeCon(){
14 System.out.println("關閉連接");
15 }
16 /**
17 * 模板方法,套用公共操作,添加個性操作
18 */
19 public void execute(){
20 beginCon();
21 run();
22 closeCon();
23 }
24 /**
25 * 個性方法,暴露給繼承的子類
26 */
27 public abstract void run();
28 }
29
繼承類2
3 public abstract class JdbcTemplateByInherit {
4 /**
5 * 公共操作:開啟連接
6 */
7 private void beginCon(){
8 System.out.println("開啟連接");
9 }
10 /**
11 * 公共操作:關閉連接
12 */
13 private void closeCon(){
14 System.out.println("關閉連接");
15 }
16 /**
17 * 模板方法,套用公共操作,添加個性操作
18 */
19 public void execute(){
20 beginCon();
21 run();
22 closeCon();
23 }
24 /**
25 * 個性方法,暴露給繼承的子類
26 */
27 public abstract void run();
28 }
29
1 package org.duyt.template.impl;
2
3 import org.duyt.template.JdbcTemplateByInherit;
4
5 public class UserDaoByIn extends JdbcTemplateByInherit{
6
7 /**
8 * 添加自定義操作
9 */
10 @Override
11 public void run() {
12 System.out.println("執行了run方法");
13 }
14
15 }
16
測試一下2
3 import org.duyt.template.JdbcTemplateByInherit;
4
5 public class UserDaoByIn extends JdbcTemplateByInherit{
6
7 /**
8 * 添加自定義操作
9 */
10 @Override
11 public void run() {
12 System.out.println("執行了run方法");
13 }
14
15 }
16
1 package org.duyt.test.template;
2
3 import org.duyt.template.JdbcTemplateByInherit;
4 import org.duyt.template.impl.UserDaoByIn;
5 import org.junit.Test;
6
7 public class TestJdbcTempbyinherit {
8
9 @Test
10 public void test01(){
11 JdbcTemplateByInherit dao = new UserDaoByIn();
12 dao.execute();
13 }
14
15 }
16
結果:2
3 import org.duyt.template.JdbcTemplateByInherit;
4 import org.duyt.template.impl.UserDaoByIn;
5 import org.junit.Test;
6
7 public class TestJdbcTempbyinherit {
8
9 @Test
10 public void test01(){
11 JdbcTemplateByInherit dao = new UserDaoByIn();
12 dao.execute();
13 }
14
15 }
16
開啟連接
執行了run方法
關閉連接
雖然看上去很簡陋,但是至少已經有了一個模板的雛形。在模板方法中,我們還可以使用“鉤子函數”來控制模板方法的流程,在模板中添加鉤子函數暴露給實現類,并修改模板方法
雖然看上去很簡陋,但是至少已經有了一個模板的雛形。在模板方法中,我們還可以使用“鉤子函數”來控制模板方法的流程,在模板中添加鉤子函數暴露給實現類,并修改模板方法
1 /**
2 * 模板方法,套用公共操作,添加個性操作
3 */
4 public void execute(){
5 beginCon();
6 if (ishookerOnOrOff()) {
7 run();
8 }
9 else{
10 System.out.println("不執行任何操作");
11 }
12
13 closeCon();
14 }
15 /**
16 * 個性方法,暴露給繼承的子類
17 */
18 public abstract void run();
19
20 /**
21 * 鉤子方法,可以用來控制模板方法的流程
22 * @return
23 */
24 public abstract boolean ishookerOnOrOff();
2 * 模板方法,套用公共操作,添加個性操作
3 */
4 public void execute(){
5 beginCon();
6 if (ishookerOnOrOff()) {
7 run();
8 }
9 else{
10 System.out.println("不執行任何操作");
11 }
12
13 closeCon();
14 }
15 /**
16 * 個性方法,暴露給繼承的子類
17 */
18 public abstract void run();
19
20 /**
21 * 鉤子方法,可以用來控制模板方法的流程
22 * @return
23 */
24 public abstract boolean ishookerOnOrOff();
修改實現類,添加鉤子方法的實現
測試結果:1 @Override
2 public boolean ishookerOnOrOff() {
3 return false;
4 }
2 public boolean ishookerOnOrOff() {
3 return false;
4 }
開啟連接
不執行任何操作
關閉連接
現在回頭看到jdbcTemplate,他并沒有通過任何實現類去繼承這個模板來調用或控制模板方法的流程,而是直接使用模板來對數據庫進行操作,這樣一來,就不能使用繼承的方式來使用模板,要升級鉤子,使用接口,使得外界能夠直接使用模板方法。新建一個鉤子接口
1 package org.duyt.template;
2
3 import java.util.Map;
4
5 public interface GenericDaoMethod {
6 public void invoke(String sql,Map params);
7 }
8
新建一個通過以組件形式出現的模板JdbcTemplateByComponent2
3 import java.util.Map;
4
5 public interface GenericDaoMethod {
6 public void invoke(String sql,Map params);
7 }
8
1 package org.duyt.template;
2
3 import java.util.Map;
4
5 public class JdbcTemplateByComponent {
6
7 private void beginCon(){
8 System.out.println("開啟連接");
9 }
10
11 private void closeCon(){
12 System.out.println("關閉連接");
13 }
14
15 public void execute(GenericDaoMethod genericDaoMethod,String sql,Map params){
16 beginCon();
17 genericDaoMethod.invoke(sql,params);
18 closeCon();
19 }
20
21 public void add(String sql,Map params){
22 execute(new GenericDaoMethod() {
23 public void invoke(String sql, Map params) {
24 System.out.println(sql);
25 System.out.println(params);
26 //使用創建的con,preparedstatement,resultset結合Sql和params執行CURD
27 }
28 }, sql, params);
29 }
30 ......其他方法略
31
32 }
33
我們看到,通過組建的方式來創建模板,需要將所有的待暴露方法都定義好在模板里,并且在每個方法中都需要實現各自的鉤子方法來使用模板方法,而對于外界,也就是調用者,只需要關心傳入的參數,和調取的方法能夠實現的業務,無需關心連接,查詢和結果集的開關等操作。基于這個思路,就基本實現了對數據庫操作的模板。
2
3 import java.util.Map;
4
5 public class JdbcTemplateByComponent {
6
7 private void beginCon(){
8 System.out.println("開啟連接");
9 }
10
11 private void closeCon(){
12 System.out.println("關閉連接");
13 }
14
15 public void execute(GenericDaoMethod genericDaoMethod,String sql,Map params){
16 beginCon();
17 genericDaoMethod.invoke(sql,params);
18 closeCon();
19 }
20
21 public void add(String sql,Map params){
22 execute(new GenericDaoMethod() {
23 public void invoke(String sql, Map params) {
24 System.out.println(sql);
25 System.out.println(params);
26 //使用創建的con,preparedstatement,resultset結合Sql和params執行CURD
27 }
28 }, sql, params);
29 }
30 ......其他方法略
31
32 }
33
posted on 2014-11-08 16:34 都較瘦 閱讀(119) 評論(0) 編輯 收藏 所屬分類: DesignPattern