行为型设计模式:关注是对象和行为的分离
模板方法:解决一个复杂的业务处理流程中,某些步骤可能有不同的处理,把行为分开,模板里面完成通用不变的;子类覆写完成个性化逻辑
有一个模拟从银行取钱功能的类
1 /// <summary> 2 /// 银行客户端 3 /// </summary> 4 public class Client 5 { 6 public void Query(int id, string name, string password) 7 { 8 if (this.CheckUser(id, password))//1.查询用户 9 { 10 double balance = this.QueryBalance(id);//2 查询余额 11 double interest = this.CalculateInterest(balance);//3计算利息 12 this.Show(name, balance, interest);//4显示到桌面 13 } 14 else 15 { 16 Console.WriteLine("账户密码错误");//5 17 } 18 } 19 20 public bool CheckUser(int id, string password) 21 { 22 return DateTime.Now < DateTime.Now.AddDays(1); 23 } 24 25 public double QueryBalance(int id) 26 { 27 return new Random().Next(10000, 1000000); 28 } 29 30 /// <summary> 31 /// 活期 定期 利率不同 32 /// </summary> 33 /// <param name="balance"></param> 34 /// <returns></returns> 35 public double CalculateInterest(double balance) 36 { 37 //if (true) 38 //{ } 39 //else 40 //{ } 41 return balance * 0.005; 42 } 43 44 //如果还有更多方法都是这样的分支。比较稳定的分支 45 //那么我们不应该把不同的行为强行塞在一起 单一职责 46 47 public void Show(string name, double balance, double interest) 48 { 49 //if (true) 50 //{ } 51 //else 52 //{ } 53 54 Console.WriteLine("尊敬的{0}客户,你的账户余额为:{1},利息为{2}", 55 name, balance, interest); 56 } 57 }
如果说利率不同,或者说要求以不同的呈现方式展示给用户(vip和普通用户),那么利用模板方法封装一个类
1 /// <summary> 2 /// 银行客户端 3 /// </summary> 4 public abstract class 5 { 6 public void Query(int id, string name, string password) 7 { 8 if (this.CheckUser(id, password)) 9 { 10 double balance = this.QueryBalance(id); 11 double interest = this.CalculateInterest(balance); 12 this.Show(name, balance, interest); 13 } 14 else 15 { 16 Console.WriteLine("账户密码错误"); 17 } 18 } 19 20 public bool CheckUser(int id, string password) 21 { 22 return DateTime.Now < DateTime.Now.AddDays(1); 23 } 24 25 public double QueryBalance(int id) 26 { 27 return new Random().Next(10000, 1000000); 28 } 29 30 /// <summary> 31 /// 活期 定期 利率不同 32 /// 不同的子类 一定有,而且不同 33 /// </summary> 34 /// <param name="balance"></param> 35 /// <returns></returns> 36 public abstract double CalculateInterest(double balance); 37 38 /// <summary> 39 /// 不同的子类 大部分相同 个别不同的 虚方法 40 /// </summary> 41 /// <param name="name"></param> 42 /// <param name="balance"></param> 43 /// <param name="interest"></param> 44 public virtual void Show(string name, double balance, double interest) 45 { 46 Console.WriteLine("尊敬的{0}客户,你的账户余额为:{1},利息为{2}", 47 name, balance, interest); 48 } 49 //private void Show(string name, double balance, double interest) 50 //{ 51 // Console.WriteLine("尊贵的{0} vip客户,您的账户余额为:{1},利息为{2}", 52 // name, balance, interest); 53 //} 54 55 }
我们看到计算利率的方法是抽象的,因为不同的存款方式利率一定会不同,而呈现给用户的方式有可能相同,有可能不同,这里定义一个基础的方法,并设置virtual使用户能够根据实际情况去复写
下面是不同的实现客户端
1 /// <summary> 2 /// 银行客户端 3 /// </summary> 4 public class ClientCurrent : AbstractClient 5 { 6 /// <summary> 7 /// 活期 定期 利率不同 8 /// </summary> 9 /// <param name="balance"></param> 10 /// <returns></returns> 11 public override double CalculateInterest(double balance) 12 { 13 return balance * 0.001; 14 } 15 }
1 /// <summary> 2 /// 银行客户端 3 /// </summary> 4 public class ClientRegular : AbstractClient 5 { 6 /// <summary> 7 /// 活期 定期 利率不同 8 /// </summary> 9 /// <param name="balance"></param> 10 /// <returns></returns> 11 public override double CalculateInterest(double balance) 12 { 13 return balance * 0.003; 14 } 15 }
1 /// <summary> 2 /// 银行客户端 3 /// </summary> 4 public class ClientVip : AbstractClient 5 { 6 /// <summary> 7 /// 活期 定期 利率不同 8 /// </summary> 9 /// <param name="balance"></param> 10 /// <returns></returns> 11 public override double CalculateInterest(double balance) 12 { 13 return balance * 0.005; 14 } 15 16 public override void Show(string name, double balance, double interest) 17 { 18 Console.WriteLine("尊贵的{0} vip客户,您的账户余额为:{1},利息为{2}", 19 name, balance, interest); 20 } 21 }
模板方法对不变的进行封装,对变化的进行提取,抽象,可复写,可以提高复用性