模板方法模式应用实例
某软件公司欲为某银行的业务支撑系统开发一个利息计算模块,利息计算流程如下:
(1) 系统根据账号和密码验证用户信息,如果用户信息错误,系统显示出错提示;
(2) 如果用户信息正确,则根据用户类型的不同使用不同的利息计算公式计算利息(如活期账户和定期账户具有不同的利息计算公式);
(3) 系统显示利息。
试使用模板方法模式设计该利息计算模块。
在图中,Account充当抽象类角色,CurrentAccount和SavingAccount充当具体子类角色。
//Account:账户类,充当抽象类。 abstract class Account { //基本方法——具体方法 public bool Validate(string account, string password) { System.out.println("账号:{0}", account); System.out.println("密码:{0}", password); //模拟登录 if (account.Equals("张无忌") && password.Equals("123456")) { return true; } else { return false; } } //基本方法——抽象方法 public abstract void CalculateInterest(); //基本方法——具体方法 public void Display() { System.out.println("显示利息!"); } //模板方法 public void Handle(string account, string password) { if (!Validate(account, password)) { System.out.println("账户或密码错误!"); return; } CalculateInterest(); Display(); } }
//CurrentAccount:活期账户类,充当具体子类。 class CurrentAccount extends Account { //覆盖父类的抽象基本方法 @Override void CalculateInterest() { System.out.println("按活期利率计算利息!"); } }
//SavingAccount:定期账户类,充当具体子类。 class SavingAccount extends Account { //覆盖父类的抽象基本方法 @Override void CalculateInterest() { System.out.println("按定期利率计算利息!"); } }
配置文件App.config,在配置文件中存储了具体子类的类名。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="subClass" value="TemplateMethodSample.CurrentAccount"/> </appSettings> </configuration>
测试代码同以往读取配置文件。
account.Handle("张无忌", "123456");
编译并运行程序,输出结果如下:
账号:张无忌 密码:123456 按活期利率计算利息! 显示利息!
如果需要更换具体子类,无须修改源代码,只需修改配置文件App.config,例如将活期账户(CurrentAccount)改为定期账户(Saving Account),只需将存储在配置文件中的具体子类
CurrentAccount改为SavingAccount。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="subClass" value="TemplateMethodSample.SavingAccount"/> </appSettings> </configuration>
重新运行客户端程序,输出结果如下:
账号:张无忌 密码:123456 按定期利率计算利息! 显示利息!
如果需要增加新的具体子类(新的账户类型),原有代码均无须修改,完全符合开闭原则。
模板方法总结
模板方法模式是基于继承的代码复用技术,它体现了面向对象的诸多重要思想,是一种使用较为频繁的模式。模板方法模式广泛应用于框架设计中,以确保通过父类来控制处理流程的逻辑顺序(如框架的初始化,测试流程的设置等)。
模板方法模式的主要优点如下:
(1) 在父类中形式化地定义一个算法,而由它的子类来实现细节的处理,在子类实现详细的处理算法时并不会改变算法中步骤的执行次序。
(2) 模板方法模式是一种代码复用技术,它在类库设计中尤为重要,它提取了类库中的公共行为,将公共行为放在父类中,而通过其子类来实现不同的行为,它鼓励我们恰当使用继承来实现代码复用。
(3) 可实现一种反向控制结构,通过子类覆盖父类的钩子方法来决定某一特定步骤是否需要执行。
(4) 在模板方法模式中可以通过子类来覆盖父类的基本方法,不同的子类可以提供基本方法的不同实现,更换和增加新的子类很方便,符合单一职责原则和开闭原则。
模板方法模式的主要缺点如下:
需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。
在以下情况下可以考虑使用模板方法模式:
(1) 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。即:一次性实现一个算法的不变部分,并将可变的行为留给子类来实现。
(2) 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
(3) 需要通过子类来决定父类算法中某个步骤是否执行,实现子类对父类的反向控制。