Design Patterns (9) - Template Method Pattern

Template (Template) The method of pattern defines a skeleton of an algorithm in the method, some steps to subclasses delay. The method of stencil such subclasses without changing the structure of the algorithm, some of the steps of the algorithm are redefined. This mode is used to create an algorithm template, the template is a method. More specifically, the method of the algorithm is defined as a set of steps, any step may be abstract, it is responsible for the subclass implementation. This algorithm can ensure that the structure remains unchanged, while providing a partially achieved by subclasses.

Directly below an example to be described.

In a coffee shop, there are two coffee drinks and tea, their brewing method are as follows:

coffee

  1. Boil the water
  2. Coffee brewed with boiling water
  3. She poured coffee into a cup
  4. Sugar and milk

tea

  1. Boil the water
  2. Tea with boiling water immersion
  3. The tea poured into the cup
  4. With lemon

We can see their steps 1 and 3, in fact, is the same, 2 and 4. different, but somewhat similar. We can extract one thing in common, to design an abstract class:

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");
	}
}

And then realize coffee and tea, respectively, through inheritance

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");
	}
}
public class Tea extends CaffeineBeverage {
	public void brew() {
		System.out.println("Steeping the tea");
	}
	public void addCondiments() {
		System.out.println("Adding Lemon");
	}
}

"hook"

The above is a basic application template method pattern, let's dig a little deeper again, tell us about the "hook" .

Hook is a method is declared abstract class again, but only empty or default implementation. There is a hook, allowing subclasses has the ability to be linked to different points of the algorithm. To not linked to the subclass own.

Then just an example, with the hooks, we can decide whether or not to override methods. If you do not provide their own methods, abstract class provides a default implementation.

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;
	}
}

In order to use the hook, we need to override it in a subclass. Then just that example, we can use caffeine drinks hook control whether a part of the algorithm, put it more clearly point is whether or not to drink added spices.

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 lemon with your tea (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;
	}
}

Test code

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();
	}
}

operation result

In this example, the hooks can serve as a control condition, the influence algorithmic flow abstract class, which is a very cool. We can conclude that the hook several uses

  • Let subclass algorithm in the optional part, or when the hook is not important for the realization of a subclass of subclasses can hook ignore this.
  • Let subclasses have the opportunity to respond to some of the template method impending (or just happened) steps. For example, called justReOrderedList()hook methods allow subclasses to perform certain actions in the internal list reorganized (e.g. reproduced data displayed on the screen).
  • Hook allows its subclasses an abstract class to make some decisions.

Design Principles

Template approach reflects a new design principle, known as the Hollywood principle: Do not call (call) us, we will call (call) you .

Hollywood can give us a principle to prevent the "dependency corruption" approach. When the high-level components depend on the underlying components, and low-level components and high-level components depend, in turn depends on the high side component assembly, the component side and low-level component dependent, dependent corruption occurs.

Under the Hollywood principle, we allow low-level components to hook themselves onto the system, but the high-level assembly will decide when and how to use these low-level components. in other words. High-level components to treat low-level components of the approach is "Do not call us, we'll call you."

In addition to the template method pattern, observer pattern and factory method pattern in the previous article in this series introduced also reflects the principles of Hollywood.

Published 295 original articles · won praise 37 · views 30000 +

Guess you like

Origin blog.csdn.net/tianshan2010/article/details/104714020