咖啡冲泡法:
1、把水煮沸
2、用沸水冲泡咖啡
3、把咖啡倒进杯子
4、加糖和牛奶
茶冲泡法
1、把水煮沸
2、用沸水冲泡茶叶
3、把茶倒进杯子
4、加柠檬
写一写代码来创建茶和咖啡:
public class Coffee {
void prepareRecipe(){
boilWater();
brewCoffeeGrinds();
pourIncup();
addSugarAndMilk();
}
public void boilWater(){
System.out.println("Boiling water");
}
public void brewCoffeeGrinds(){
System.out.println("Dripping Coffee through filter");
}
public void pourIncup(){
System.out.println("Pouring into cup");
}
public void addSugarAndMilk(){
System.out.println("Adding sugar and Milk");
}
}
public class Tea {
void prepareRecipe(){
boilWater();
steepTeaBag();
pourIncup();
addLemon();
}
public void boilWater(){
System.out.println("Boiling water");
}
public void steepTeaBag(){
System.out.println("Steeping the tea");
}
public void pourIncup(){
System.out.println("Pouring into cup");
}
public void addLemon(){
System.out.println("Adding lemon");
}
}
仔细看看,咖啡和茶1、3步骤完全一样,可以放到基类中,2、4步骤实际也是一样,只是应用在不同的饮料。
抽象prepareRecipe()
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 Teaa extends CaffeineBeverage{
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("Steeping the tea");
}
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println("Adding Lemon");
}
}
public class Coffeee extends CaffeineBeverage{
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("Dripping coffee through filter");
}
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println("Adding Sugar and Milk");
}
}
相对于原来的:由CaffeineBeverage类主导一切,它拥有算法,而且保护这个算法。对子类来说,代码复用最大化。算法只存在一个地方,所以容易修改。
模板方法定义了一个算法的步骤,并允许子类为一个或者多个步骤提供实现。
还可以对模板方法进行挂钩:
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;
}
}
使用钩子:
public class CoffeeWithHook extends CaffeineBeverageWithHook{
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("Dripping coffee through filter");
}
@Override
void addCondiments() {
// TODO Auto-generated method stub
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 answerString=null;
System.out.println("would you like milk and sugar with your coffee(y/n)");
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
try{
answerString=in.readLine();
}catch(IOException ioe){
System.out.println("IO error");
}
if(answerString==null)
return "no";
return answerString;
}
}
public class TeaWithHook extends CaffeineBeverageWithHook{
@Override
void brew() {
// TODO Auto-generated method stub
System.out.println("Steeping the tea");
}
@Override
void addCondiments() {
// TODO Auto-generated method stub
System.out.println("Adding lemon");
}
public boolean customerWantsCondiments(){
String answer=getUserInput();
if(answer.toLowerCase().startsWith("y")){
return true;
}else {
return false;
}
}
private String getUserInput(){
String answerString=null;
System.out.println("would you like milk and sugar with your coffee(y/n)");
BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
try{
answerString=in.readLine();
}catch(IOException ioe){
System.out.println("IO error");
}
if(answerString==null)
return "no";
return answerString;
}
}
test
public class BeverageTestDrive {
public static void main(String[]args){
TeaWithHook teaHook=new TeaWithHook();
CoffeeWithHook coffeeHook=new CoffeeWithHook();
System.out.println("\nMaking the tea...");
teaHook.prepareRecipe();
System.out.println("\nMaking the coffee...");
coffeeHook.prepareRecipe();
}
}
result
Making the tea...
Boiling water
Steeping the tea
Pouring into cup
would you like milk and sugar with your coffee(y/n)
n
Making the coffee...
Boiling water
Dripping coffee through filter
Pouring into cup
would you like milk and sugar with your coffee(y/n)
y
Adding sugar and milk
新的设计原则:好莱坞原则,防止依赖腐败。换句话说,高层组件对待底层组件的方式是“别调用我们,我们会调用你们”。
让我们来排序一些鸭子:利用数组的排序模板方法提供的算法
public class Duck implements Comparable{
String name;
int weight;
public Duck(String name,int weight){
this.name=name;
this.weight=weight;
}
public String toString(){
return name+"weights"+weight;
}
public int compareTo(Object object){
Duck otherDuck=(Duck)object;
if(this.weight<otherDuck.weight)
return -1;
else if(this.weight==otherDuck.weight){
return 0;
}else return 1;
}
}
import java.util.Arrays;
public class DuckSortTestDrive {
public static void main(String[]args){
Duck []ducks={
new Duck("Daffy", 8),
new Duck("Dewey", 2),
new Duck("Howard", 7),
new Duck("Louie", 2),
new Duck("Huey", 2)
};
System.out.println("Before sorting:");
display(ducks);
Arrays.sort(ducks);
System.out.println("\nAfter sorting:");
display(ducks);
}
public static void display(Duck[]ducks){
for(int i=0;i<ducks.length;i++)
System.out.println(ducks[i]);
}
}
result:
Before sorting:
Daffyweights8
Deweyweights2
Howardweights7
Louieweights2
Hueyweights2
After sorting:
Deweyweights2
Louieweights2
Hueyweights2
Howardweights7
Daffyweights8
模板方法和策略有点类似,但是模板方法 对算法有更多的控制权,而策略是通过对象组合的方式,让客户可以选择算法实现。