设计模式之模板方法模式

   模板方法模式定义了一套算法调用步骤的模板,通过继承,子类可以对一个或多个步骤提供实现。当需要扩展时,只需要添加子类即可,而且子类可以复用父类的代码。

 模板方法模式的类图如下:

  

 

 下面以泡茶和冲咖啡为例

  抽象出泡茶和冲咖啡的咖啡因饮料类

/**
	定义了模板方法的类,抽象出咖啡和茶的咖啡因饮料类
**/
public abstract class CaffeineBeverage
{
	/**
		模板方法,调用一系列的步骤,实现制作饮料的步骤
	**/
	public final void  prepareRecipe()
	{
		boilWater();
		brew();
		pourInCup();
		if(custormerWantCondiments())
		addCondiments();
		
	}
	/**
		由于把水煮沸的步骤对于任何饮料都是一样的,则父类直接实现该方法
	**/
	public void boilWater()
	{
		System.out.println("boil water");
	}
	public abstract void brew();
	public abstract void addCondiments();
	public void pourInCup()
	{
		System.out.println("pour In cup");
	}
	/**
	子类可以选择实现的“钩子”方法
	**/
	public boolean custormerWantCondiments()
	{
		return true;
	}
}

 Tea类

 

/**
	继承了模板方法的类Tea,没有实现钩子方法
**/
public class Tea extends CaffeineBeverage
{

	public  void brew()
	{
		System.out.println("Steeping the tea");
	}
	public void addCondiments()
	{
	
		System.out.println("adding lemon");
	}

	
}

 Coffee类

import java.io.*;
/**
	继承了模板方法的类Coffee类
**/
public class Coffee extends CaffeineBeverage
{

	public void brew()
	{
		System.out.println("Dripping Coffee through filter");
	}
	public  void addCondiments()
	{
	
		System.out.println("adding sugar");
	}
	/**
	子类可以选择实现的“钩子”方法
	**/
	public boolean custormerWantCondiments()
	{
			String answer=getUserInput();
			if(answer.equals("y"))
			{
				return true;
			}
			return false;
	}
	private String getUserInput()
	{
		String answer=null;
		System.out.println("would you like milk and sugar in your coffee?");
		BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
		try
		{
			answer=in.readLine();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		if(answer==null)
		{
			return "n";
		}
		return answer;
	
	}
}

 测试类

public class Test
{
	public static void main(String[] args)
	{
		Coffee coffee=new Coffee();
		System.out.println("Making coffee....");
		coffee.prepareRecipe();
		Tea tea=new Tea();
		System.out.println("Making tea....");
		tea.prepareRecipe();
	
	
	}
}

 运行结果

 可以看出模板方法定义的步骤里面有三种不同类型的方法:

 1.由父类直接实现的方法:比如上例中的boilWater和pourInCup方法,对于Coffee和Tea来说,都是一样的,所以可以复用,可以定义为final

   2.由子类实现的方法:比如上例中的brew方法

   3.子类可选择实现的方法,比如上例中的customerWantCondiments()方法。

  由模板方法模式中的“钩子”,可以引申出一个设计原则——“好莱坞原则”,“别电话给我,我会打电话给你”,就是说,低层组件可以将自己挂钩到系统上,但是由高层组件决定什么时候和怎样使用这些底层组件,所以对于高层组件来说,其对待低层组件的方式是“别调用我,我会调用你们”。像上例中的customerWantCondiments()方法,就是由子类实现,父类调用。

 模板方法的应用之一是用模板方法排序。

 Arrays类中提供了一个sort方法,sort方法实际上调用了一个私有的mergeSort()方法

 

 mergeSort方法是一个模板方法,我们可以通过改变比较的条件实现自己的排序,我们需要实现的是Comparable接口中的compareTo()方法。

 比如说我们要将学生按成绩排序。

  写一个Student类,实现Comparable接口

public class Student implements Comparable 
{
	public int score;
	public String name;
	public Student(String name,int score)
	{
		this.name=name;
		this.score=score;
	}
	public int compareTo(Object object)
	{
		Student otherStudent=(Student)object;
		if(this.score>otherStudent.score)
		{
			return 1;
		}
		else if(this.score==otherStudent.score)
		{
			return 0;
		}
		else
		{
			return -1;
		}
	}
}

 测试类

 

import java.util.*;
public class TestSort
{
	public static void main(String[] args)
	{
		Student[] stu={
			new Student("qing",100),
			new Student("chen",90),
			new Student("zhou",80),
			new Student("ddd",50)
		};
		System.out.println("before sorting....");
		display(stu);
		System.out.println("after sorting....");
		Arrays.sort(stu);
		display(stu);
	
	}
	public static void display(Student[] stu)
	{
		for(Student s:stu)
		{
			System.out.println(s.name+"\t"+s.score);
		
		}
	}
}

 运行结果是

 

 模板方法模式,策略模式,工厂方法模式的比较

 

posted on 2015-01-26 13:19  qingfei  阅读(201)  评论(0编辑  收藏  举报