1:模板方法模式
模板方法模式是一种行为设计模式,它在超类中定义了一个算法的框架,允许子类在不修改结构的情况下重写算法的特定步骤。
2:模板方法问题
在面向对象程序设计过程中,程序员常常会遇到这种情况:设计一个系统时知道了算法所需的关键步骤,而且确定了这些步骤的执行顺序,但某些步骤的具体实现还未知,或者说某些步骤的实现与具体的环境相关。
例如,去银行办理业务一般要经过以下4个流程:取号、排队、办理具体业务、对银行工作人员进行评分等,其中取号、排队和对银行工作人员进行评分的业务对每个客户是一样的,可以在父类中实现,但是办理具体业务却因人而异,它可能是存款、取款或者转账等,可以延迟到子类中实现。
这样的例子在生活中还有很多,例如,一个人每天会起床、吃饭、做事、睡觉等,其中“做事”的内容每天可能不同。我们把这些规定了流程或格式的实例定义成模板,允许使用者根据自己的需求去更新它,例如,简历模板、论文模板、Word 中模板文件等。
3:模板方法解决方案
模板方法模式建议将算法分解为一系列步骤,然后将这些步骤改写为方法,最后在 “模板方法” 中依次调用这些方法。步骤可以是抽象的,也可以有一些默认的实现。为了能够使用算法,客户端需要自行提供子类并实现所有的抽象步骤。如有必要还需重写一些步骤(但这一步中不包括模板方法自身)。
4:模板方法结构
- 抽象类(AbstractClass)会声明作为算法步骤的方法,以及依次调用它们的实际模板方法。算法步骤可以被声明为抽象类型,也可以提供一些默认实现。
- 具体类(ConcreteClass)可以重写所有步骤,但不能重写模板方法自身。
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
abstract class NetWork { protected String userName; protected String password;
NetWork() { }
public boolean post(String msg) { if (logIn(userName, password)) { boolean result = sendData(msg); logOut(); return result; } return false; }
abstract boolean logIn(String userName, String password);
abstract boolean sendData(String msg);
abstract void logOut(); }
class QQ extends NetWork { public QQ(String username, String password) { this.userName = username; this.password = password; }
@Override boolean logIn(String userName, String password) { System.out.println("Name: " + userName); System.out.print("password: "); for (int i = 0; i < this.password.length(); i++) { System.out.print("*"); } System.out.println("成功登陆QQ"); return true; }
@Override boolean sendData(String msg) { boolean messagePosted = true; if (messagePosted) { System.out.println("信息: '" + msg + "' 已在QQ发送"); return true; } else { return false; } }
@Override void logOut() { System.out.println("User: " + userName + "已退出QQ"); } }
class WeChat extends NetWork { public WeChat(String username, String password) { this.userName = username; this.password = password; }
@Override boolean logIn(String userName, String password) { System.out.println("Name: " + userName); System.out.print("password: "); for (int i = 0; i < this.password.length(); i++) { System.out.print("*"); } System.out.println("成功登陆微信"); return true; }
@Override boolean sendData(String msg) { boolean messagePosted = true; if (messagePosted) { System.out.println("信息: '" + msg + "' 已在微信发送"); return true; } else { return false; } }
@Override void logOut() { System.out.println("User: " + userName + "已退出微信"); } }
public class TemplateMethod { public static void main(String[] args) { NetWork netWork = null; Scanner scanner = new Scanner(System.in); System.out.println("请输入用户名:"); String userName = scanner.nextLine(); System.out.println("请输入密码"); String password = scanner.nextLine(); System.out.println("请输入消息"); String msg = scanner.nextLine(); System.out.println("请选择消息发送方式:1-QQ 2-微信"); String choice = scanner.nextLine(); switch (choice) { case "1": netWork = new QQ(userName, password); break; case "2": netWork = new WeChat(userName, password); break; default: } netWork.post(msg); } }
|
输出如下:
1 2 3 4 5 6 7 8 9 10 11 12
| 请输入用户名: 张三 请输入密码: 123456 请输入消息: Hello World 请选择消息发送方式:1-QQ 2-微信 1 Name: 张三 password: ******成功登陆QQ 信息: 'Hello World' 已在QQ发送 User: 张三已退出QQ
|
5:模板方法适用场景
- 当你只希望客户端扩展某个特定算法步骤, 而不是整个算法或其结构时, 可使用模板方法模式。
- 当多个类的算法除一些细微不同之外几乎完全一样时, 你可使用该模式。 但其后果就是, 只要算法发生变化, 你就可能需要修改所有的类。
6:模板方式优缺点
优点 |
缺点 |
你可仅允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小。 |
部分客户端可能会受到算法框架的限制。 |
你可将重复代码提取到一个超类中。 |
通过子类抑制默认步骤实现可能会导致违反_里氏替换原则_。 |
|
模板方法中的步骤越多, 其维护工作就可能会越困难。 |
7:模板方法模式与其他模式关系
- 工厂方法模式是模板方法模式的一种特殊形式。同时,工厂方法可以作为一个大型模板方法中的一个步骤。
- 模板方法基于继承机制:它允许你通过扩展子类中的部分内容来改变部分算法。策略模式基于组合机制:你可以通过对相应行为提供不同的策略来改变对象的部分行为。模板方法在类层次上运作,因此它是静态的。策略在对象层次上运作,因此允许在运行时切换行为。
8:模板模式举例
模板方法模式中:抽象类就像领导,确定要干哪些事,怎么干。具体类就是员工,负责每件事的落实,同时,每个员工的工作效果不一样,也影响了最后的结果。
9:参考