下面通过代码来模拟一个去银行查询的业务场景。代码如下:
public class BankClient { /// <summary> /// 查询 /// </summary> public void Query(int id, string name, string password) { if (CheckUser(id, password)) { double balance = this.QueryBanlance(id); double interest = this.CalculateInterest(balance); this.Show(name,balance,interest); } else { Console.WriteLine("账号密码错误!"); } } /// <summary> /// 验证用户 /// </summary> public bool CheckUser(int id, string password) { return true; } /// <summary> /// 查询余额 /// </summary> public double QueryBanlance(int id) { return new Random().Next(1000,100000); } /// <summary> /// 计算利息 /// </summary> public double CalculateInterest(double balance) { return balance * 0.005; } public void Show(string name, double balance, double interest) { Console.WriteLine($"尊敬的 {name} 客户,您的账户余额为:{balance} ,利息为:{interest}"); } }
上面的代码把整个业务写一个类里面,各种逻辑写成方法。这只是在理想状态下,大家都知道银行的利息计算方法分为:活期和定期,并且他们的利率不同。那么,一般做法就是在CalculateInterest方法中加if判断来处理,如果Show方法也要根据存款类型来输出提示信息,像这样在多个方法中频繁的出现相同逻辑的分支,我们的代码就不应该这么写了,因为不同行为应该分开写。
修改后的代码如下:
public abstract class AbstractClient { /// <summary> /// 查询 /// </summary> public void Query(int id, string name, string password) { if (CheckUser(id, password)) { double balance = this.QueryBanlance(id); double interest = this.CalculateInterest(balance); this.Show(name, balance, interest); } else { Console.WriteLine("账号密码错误!"); } } /// <summary> /// 验证用户 /// </summary> public bool CheckUser(int id, string password) { return true; } /// <summary> /// 查询余额 /// </summary> public double QueryBanlance(int id) { return new Random().Next(1000, 100000); } /// <summary> /// 活期/定期 ///选择抽象方法的原因: 不同的子类,一定不同,而且不同 /// </summary> public abstract double CalculateInterest(double balance); //在不同的子类中,大部分相同,个别不同的,这种用虚方法 public virtual void Show(string name, double balance, double interest) { Console.WriteLine($"尊敬的 {name} 客户,您的账户余额为:{balance} ,利息为:{interest}"); } } public class ClientRegular:AbstractClient { /// <summary> /// 定期利率计算方法 /// </summary> public override double CalculateInterest(double balance) { return balance * 0.003; } } public class ClientCurrent : AbstractClient { /// <summary> /// 活期利率计算方法 /// </summary> public override double CalculateInterest(double balance) { return balance * 0.002; } } internal class Program { static void Main(string[] args) { AbstractClient client = new ClientCurrent(); client.Query(123,"谭勇君","123456"); Console.ReadKey(); } }
如上就是模板模式,它就是通过一个抽象类和不同的子类来解决问题,AbstractClient类就相当于模板。
模板模式主要是应对一个业务处理中有多个步骤,然后这些步骤中的某个步骤可能出现不同的情况,我们就把这些不同的步骤写到不同的子类,把固定不变的写到父类。