第十课 模板方法模式
其实说实话,模板方法真的是实际开发中最常用的模式了。相信大家有意无意肯定都用过。为什么这么说呢。因为模板方法的亮点,就是代码复用。这是对广大开发人员最有吸引力的吧。
举个简单例子,大家都做过数据库操作吧。其实别管什么语言,什么数据库,基本的处理方法是相同的,我来列一下,估计大家就明白了。
1. 获得数据库连接
2. 执行数据库操作
3. 关闭数据库连接
相信大家对上述做法没有意见吧。
那么这样就体现问题了。我每次执行数据库操作,都要先打开连接,最后关闭连接。这样是不是都是重复劳动啊。要是一不小心忘了关闭连接,很可能就导致达到最大连接数,导致系统不能使用。所以估计应该都用过这种方式吧。
public void Run()
{
Connect();
DoSQL();
Disconnect();
}
这样做的好处呢,首先是将通用的打开连接和关闭连接拿出来共用。其次定义了固定的实行操作的流程,(先打开,最后关闭,这样避免了忘了关连接的情况)减少了出错概率。是日常开发中经常使用的呢。
记得在哪里看到过这么一句话“如果你只想要学习一种设计模式的话,那么毫无疑问应该选择模板方法模式”。为什么这么说呢,嘿嘿,谁希望整天去敲一堆堆一样的代码啊,即使Ctrl+C Ctrl+V也很麻烦不是,而且还容易漏。
所以这一讲大家好好学吧,最实际了。
下面来段“示意”性代码,就用上面说的数据操作了。
1. using System;
2. using System.Collections.Generic;
3. using System.Text;
4. using System.Data;
5. using System.Data.SqlClient;
6.
7. namespace 模板方法模式
8. {
9. public class DBSample
10. {
11. static void Main (string[] args)
12. {
13. DBBase2 c;
14.
15. c = new Categories();
16. c.Run("select * from Categories");
17.
18. c = new Products();
19. c.Run("select * from Products");
20.
21. Console.Read();
22.
23. }
24. }
25.
26. abstract class DBBase2
27. {
28.
29. //protected SqlConnection conn;
30.
31. protected void Connect()
32. {
33. //this.conn = new SqlConnection("Server=.;User Id=sa;Password=sa;Database=Northwind");
34. Console.WriteLine("建立连接");
35. }
36.
37. protected void Disconnect()
38. {
39. //this.conn.Close();
40. Console.WriteLine("关闭连接");
41. }
42.
43. protected abstract void DoSQL(string sql);
44.
45. public void Run(string sql)
46. {
47. Connect();
48. DoSQL(sql);
49. Disconnect();
50.
51. }
52. }
53.
54. class Categories : DBBase2
55. {
56. protected override void DoSQL(string sql)
57. {
58. //SqlCommand cmd = new SqlCommand(sql, this.conn);
59. Console.WriteLine("执行SQL:"+sql);
60. }
61. }
62.
63. class Products : DBBase2
64. {
65. protected override void DoSQL(string sql)
66. {
67. //SqlCommand cmd = new SqlCommand(sql, this.conn);
68. Console.WriteLine("执行SQL:" + sql);
69. }
70. }
71. }
72.
很简单的处理方式,估计大家原来写SQLHelper的时候经常用吧。随手写得,例子的数据库是用的经典的Northwind。
其实这里大家有印象吗,前面也提起过模板方法的。记得应该是工厂方法那里吧。那么留个作业个大伙。结合工厂方法模式,把上面我随手写得例子扩展下,让他能通过配置文件支持Oracle数据库和SQL数据库。不简单哦,好好想想吧。
这一块也没有什么好讲的了,给大家一个Java与模式中的例子吧。
首先是基类Account 注意这里的作用域修饰符的使用,final 特别要注意。(不过其实不加也没太大影响,但是加了的话,就能过确定绝对不能重写此方法了,就定死了规矩)
1. package com.javapatterns.templatemethod.InterestRate;
2.
3. abstract public class Account
4. {
5. protected String accountNumber;
6.
7. public Account()
8. {
9. accountNumber = null;
10. }
11.
12. public Account(String accountNumber)
13. {
14. this.accountNumber = accountNumber;
15. }
16.
17. final public double calculateInterest()
18. {
19. double interestRate = doCalculateInterestRate();
20. String accountType = doCalculateAccountType();
21. double amount = calculateAmount(accountType, accountNumber);
22.
23. return amount * interestRate;
24. }
25.
26. abstract protected String doCalculateAccountType() ;
27.
28. abstract protected double doCalculateInterestRate() ;
29.
30. final public double calculateAmount(String accountType, String accountNumber)
31. {
32. //retrieve amount from database...here is only a mock-up
33. return 7243.00D;
34. }
35. }
36.
接着两个具体实现类
1. package com.javapatterns.templatemethod.InterestRate;
2.
3. public class CDAccount extends Account
4. {
5. public String doCalculateAccountType()
6. {
7. return "Certificate of Deposite";
8. }
9.
10. public double doCalculateInterestRate()
11. {
12. return 0.065D;
13. }
14. }
15.
1. package com.javapatterns.templatemethod.InterestRate;
2.
3. public class MoneyMarketAccount extends Account
4. {
5. public String doCalculateAccountType()
6. {
7. return "Money Market";
8. }
9.
10. public double doCalculateInterestRate()
11. {
12. return 0.045D;
13. }
14. }
15.
最后看客户端调用:
1. package com.javapatterns.templatemethod.InterestRate;
2.
3. public class Client
4. {
5. private static Account acct = null;
6.
7. public static void main(String[] args)
8. {
9. acct = new MoneyMarketAccount();
10. System.out.println("Interest earned from Money Market account = " + acct.calculateInterest());
11.
12. acct = new CDAccount();
13. System.out.println("Interest earned from CD account = " + acct.calculateInterest());
14. }
15. }
16.
作者:王文斌