每天一个设计模式之模板方法设计模式
此系列的文章是来源自head first 设计模式 代码也是来源于此书,也自己的一个总结
首先是我们谈到什么是模板方法,模板方法顾名思义它的作用是一个模板我们可以根据这个模板对这个程序进行添加和修改 在标准定义中模板方法是指 在一个方法中定义一个算法的骨架,而将一些步骤延迟到之类中进行,这样在不影响算法的结构下,重新定义算法的某系步骤
我们根据具体的代码来看一下一个简单的模板方法模式是怎样的实现的
首先我们定义一个模板抽象类
public abstract class CaffeineBeverage {
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
}
这是一个抽象的类,已经定义了一些一些骨干和需要重写的方法,下面我们就需要一个模板之类进行继承重写这个抽象方法
public class Coffee extends CaffeineBeverage {
public void brew() {
System.out.println("Dripping Coffee through filter");
}
public void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
}
我们这个类对抽象的类的重写,既保留了抽象类的骨干。又实现了我们自身需要的一些方法。这是一个简单的抽象方法。
下面我们将要接受对模板方法进行g挂钩。
钩子是声明在抽象类中的一个方法,通过实现钩子可以让之类有能力对算法的不同点进行挂钩。要不要挂钩,由之类自行决定。
下面是一个加了钩子方法的抽象方法。
public abstract class CaffeineBeverageWithHook {
void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
boolean customerWantsCondiments() {
return true;
}
}
通过使用钩子来控制是否执行某部分的算法。
import java.io.*;
public class CoffeeWithHook extends CaffeineBeverageWithHook {
public void brew() {
System.out.println("Dripping Coffee through filter");
}
public void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
public boolean customerWantsCondiments() {
String answer = getUserInput();
if (answer.toLowerCase().startsWith("y")) {
return true;
} else {
return false;
}
}
private String getUserInput() {
String answer = null;
System.out.print("Would you like milk and sugar with your coffee (y/n)? ");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
answer = in.readLine();
} catch (IOException ioe) {
System.err.println("IO error trying to read your answer");
}
if (answer == null) {
return "no";
}
return answer;
}
}
下面是另外一个实现类
import java.io.*;
public class TeaWithHook extends CaffeineBeverageWithHook {
public void brew() {
System.out.println("Steeping the tea");
}
public void addCondiments() {
System.out.println("Adding Lemon");
}
public boolean customerWantsCondiments() {
String answer = getUserInput();
if (answer.toLowerCase().startsWith("y")) {
return true;
} else {
return false;
}
}
private String getUserInput() {
// get the user's response
String answer = null;
System.out.print("Would you like milk and sugar with your coffee (y/n)? ");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try {
answer = in.readLine();
} catch (IOException ioe) {
System.err.println("IO error trying to read your answer");
}
if (answer == null) {
return "no";
}
return answer;
}
}
最后是一个测试类
public class BeverageTestDrive {
public static void main(String[] args) {
Tea tea = new Tea();
Coffee coffee = new Coffee();
System.out.println("\nMaking tea...");
tea.prepareRecipe();
System.out.println("\nMaking coffee...");
coffee.prepareRecipe();
TeaWithHook teaHook = new TeaWithHook();
CoffeeWithHook coffeeHook = new CoffeeWithHook();
System.out.println("\nMaking tea...");
teaHook.prepareRecipe();
System.out.println("\nMaking coffee...");
coffeeHook.prepareRecipe();
}
}
通过使用钩子我们可以控制之类是否进行模板的重写。当我们认为我们的之类适合算法的这一部分,我就讲使用钩子。
上面是关于模板方法的原理,下面我们就看一下在Java 中有哪些使用了模板方法
先来一个SWING的,
import java.awt.*;
import javax.swing.*;
public class MyFrame extends JFrame {
public MyFrame(String title) {
super(title);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(300,300);
this.setVisible(true);
}
public void paint(Graphics graphics) {
super.paint(graphics);
String msg = "I rule!!";
graphics.drawString(msg, 100, 100);
}
public static void main(String[] args) {
MyFrame myFrame = new MyFrame("Head First Design Patterns");
}
}
可能你会感觉这个和咱们前面说的不一样啊,这有讲关于模板方法的吗,好像没有啊。
咱们慢慢的分析来看。首先咱们这个类继承自JFrame 这个类就相当于咱们的抽象类通过继承这个类,我们重写了paint这个方法,这个方法就是钩子,通过这个方法我们来实现我们自己的一些算法和逻辑,如果我们重写这个方法,程序就会使用默认的方法。
我们在来看看另外的一个例子
这是一个关于applet的,我们先看代码在对代码中的实现进行分析
import java.applet.Applet;
import java.awt.Graphics;
public class MyApplet extends Applet {
String message;
public void init() {
message = "Hello World, I'm alive!";
repaint();
}
public void start() {
message = "Now I'm starting up...";
repaint();
}
public void stop() {
message = "Oh, now I'm being stopped...";
repaint();
}
public void destroy() {
message = "Goodbye, cruel world";
repaint();
}
public void paint(Graphics g) {
g.drawString(message, 5, 15);
}
}
这个程序也是很典型的模板方法,我们继承重写了applet
的一些方法,如果我们不重写这些方法,他们就会使用默认的方法,但是当我们重写了这些方法,他们这些方法就要按照我们的算法逻辑进行操作。
这个是自己根据书本上的内容写的一篇总结,文章肯定有一些不通顺或者一些错误,谢谢大家查看,并指出错误。。