1.定义
模板⽅法模式(Template Method)是⼀种⾏为设计模式, 它在超类中定义了⼀个算法的框架, 允许⼦类在不修改结构的情况下重写算法的特定步骤。
基本思想是:算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改
2.代码结构
3.代码示例
需求:写了一个机器人可以向指定的网站发送消息
抽象类:规定流程是怎么做的
public abstract class Network { String userName; String password; Network() {} // 将数据发布到网络 public boolean post(String message) { // 发布消息前的身份验证,每个网站使用不同的身份验证方法 if (logIn(this.userName, this.password)) { // 发送消息 boolean result = sendData(message.getBytes()); // 退出登陆 logOut(); return result; } return false; } abstract boolean logIn(String userName, String password); abstract boolean sendData(byte[] data); abstract void logOut(); }
向Twitter发送消息具体类:
public class Twitter extends Network { public Twitter(String userName, String password) { this.userName = userName; this.password = password; } @Override public boolean logIn(String userName, String password) { System.out.println("\n正在检查用户名和密码"); System.out.println("用户名: " + this.userName); System.out.print("密码: "); for (int i = 0; i < this.password.length(); i++) { System.out.print("*"); } simulateNetworkLatency(); System.out.println("\n\n成功登陆"); return true; } @Override public boolean sendData(byte[] data) { boolean messagePosted = true; if (messagePosted) { System.out.println("消息: '" + new String(data) + "' 已经发布到 Twitter 上"); return true; } else { return false; } } @Override public void logOut() { System.out.println("用户: '" + userName + "'已经从Twitter 退出"); } private void simulateNetworkLatency() { try { int i = 0; System.out.println(); while (i < 10) { System.out.print("."); Thread.sleep(500); i++; } } catch (InterruptedException ex) { ex.printStackTrace(); } } }
向Facebook发送消息具体类:
public class Facebook extends Network { public Facebook(String userName, String password) { this.userName = userName; this.password = password; } @Override public boolean logIn(String userName, String password) { System.out.println("\n正在检查用户名和密码"); System.out.println("用户名: " + this.userName); System.out.print("密码: "); for (int i = 0; i < this.password.length(); i++) { System.out.print("*"); } simulateNetworkLatency(); System.out.println("\n\n 成功登陆 Facebook"); return true; } @Override public boolean sendData(byte[] data) { boolean messagePosted = true; if (messagePosted) { System.out.println("消息: '" + new String(data) + "' 已经发布到 Facebook 上"); return true; } else { return false; } } @Override public void logOut() { System.out.println("用户: '" + userName + "' 已经从Facebook 退出"); } private void simulateNetworkLatency() { try { int i = 0; System.out.println(); while (i < 10) { System.out.print("."); Thread.sleep(500); i++; } } catch (InterruptedException ex) { ex.printStackTrace(); } } }
客户端:
public class Client { public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); Network network = null; System.out.print("请输入用户名: "); String userName = reader.readLine(); System.out.print("请输入密码: "); String password = reader.readLine(); // Enter the message. System.out.print("请输入内容: "); String message = reader.readLine(); System.out.println("\n请选择发布消息的社交平台\n" + "1 - Facebook\n" + "2 - Twitter"); int choice = Integer.parseInt(reader.readLine()); // 根据用户选择的不同登陆相应的网站发送消息 if (choice == 1) { network = new Facebook(userName, password); } else if (choice == 2) { network = new Twitter(userName, password); } network.post(message); } }
输出内容:
请输入用户名: zhangsan 请输入密码: lisi 请输入内容: 我爱中国共产党 请选择发布消息的社交平台 1 - Facebook 2 - Twitter 2 正在检查用户名和密码 用户名: zhangsan 密码: **** .......... 成功登陆 消息: '我爱中国共产党' 已经发布到 Twitter 上 用户: 'zhangsan'已经从Twitter 退出
4.优点
你可仅允许客户端重写⼀个⼤型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减⼩。
你可将重复代码提取到⼀个超类中。
5.缺点
部分客户端可能会受到算法框架的限制。
通过⼦类抑制默认步骤实现可能会导致违反⾥⽒替换原则。
每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大
6.使用场景
当你只希望客户端扩展某个特定算法步骤, ⽽不是整个算法或其结构时, 可使⽤模板⽅法模式。
当多个类的算法除⼀些细微不同之外⼏乎完全⼀样时, 你可使⽤该模式。 但其后果就是, 只要算法发⽣变化, 你就可能需要修改所有的类。
转载请注明:西门飞冰的博客 » 设计模式—模板方法模式