设计模式-模板方法模式 策略模式
来源:互联网 发布:阿里算法工程师p6待遇 编辑:程序博客网 时间:2024/06/06 02:08
模板方法模式定义
模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
模板方法非常常见,对创建框架来说,由框架控制如何做事情,而由你(使用这个框架的人)指定框架算法中每个步骤的细节。
举个咖啡和茶的例子
用模版方法实现代码复用,让茶,咖啡等一类制作方法类似的饮料借用一个算法框架来实现
茶的制作方法:1.把水煮沸 2.用沸水浸泡茶叶 3.把茶倒进杯子4.加柠檬
咖啡的制作方法:1.把水煮沸 2.用沸水冲泡咖啡 3.把咖啡倒进杯子4.加牛奶或者糖
可以看出两者的制作过程其实是采用了相同的算法:
1.把水煮沸
2.用沸水冲泡咖啡或者茶
3.把饮料倒进杯子
4.加入调料
我们把这个咖啡因类饮料的制作方法抽象出来 实现一个模板方法,模板方法定义了一个算法的步骤,并允许子类为一个或者多个步骤提供实现
public abstract class CaffeineBeverage { //prepareRecipe是我们的模板方法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 Tea extends CaffeineBeverage {public void brew() {System.out.println("Steeping the tea");}public void addCondiments() {System.out.println("Adding Lemon");}}
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");}}对模板方法进行挂钩
钩子(hook)是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。
某些步骤是可选的,所以可以将这些步骤实现成钩子,而不是实现成抽象方法,这样就可以让抽象类的子类的负荷减轻。
比如,也可以利用钩子做条件控制,影响抽象类中的算法流程:钩子方法在抽象类中有默认实现返回true,放在抽象类的if条件语句中,子类可以覆盖也可以不覆盖这个钩子方法。
上述例子可以对ddCondiments()方法进行挂钩,让子类自由选择要不要加调料,抽象类重写如下:
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;}}子类需要实现customerWantsCondiments方法,进行判断是否要进行加调料的操作。而实现这个方法要根据顾客的需求来定,getUserInput()方法得到顾客输入的需求信息
//咖啡子类 挂钩版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");} //对判断条件的实现 如果输入y就加入调料public boolean customerWantsCondiments() {String answer = getUserInput();if (answer.toLowerCase().startsWith("y")) {return true;} else {return false;}}private String getUserInput() {// get the user's responseString 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();}
模版方法模式是一个很常见的模式,这是因为对创建框架来说,这个模式很方便可以做到有框架控制如何做事情,而由你指定框架中每个步骤的细节,在实际应用中模版方法有很多实现方法。
下面的例子是用模版方法进行排序
class Student implements Comparable<Student>{ private String name; private int age; private float score; public Student(String name, int age, float score) { this.name = name; this.age = age; this.score = score; } public String toString() { return name+"\t\t"+age+"\t\t"+score; } @Override public int compareTo(Student o) { if(this.score>o.score)//score是private的,为什么能够直接调用,这是因为在Student类内部 return -1;//由高到底排序 else if(this.score<o.score) return 1; else{ if(this.age>o.age) return 1;//由底到高排序 else if(this.age<o.age) return -1; else return 0; } }}public class ComparableDemo01 { public static void main(String[] args) { Student stu[]={new Student("zhangsan",20,90.0f), new Student("lisi",22,90.0f), new Student("wangwu",20,99.0f), new Student("sunliu",22,100.0f)}; Arrays.sort(stu); for(Student s:stu) { System.out.println(s); } }}排序的实现看起来更像是策略模式,因为策略模式使用对象组合,但是在策略模式中,你所组合的类实现了整个算法。数组所实现的排序算法并不完整,它需要一个类填补 compareTo()方法的实现。因此认为这更像模版方法
策略模式
定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
这个原则的思考方式是,把会变化的部分取出并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的其他部分
这个模式涉及到三个角色:
● 环境(Context)角色:持有一个Strategy的引用。
● 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
● 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
策略模式网上的例子有很多,也比较简单,与上面一个排序做对比,下面用comparator实现的排序用的就是策略模式
import java.util.Comparator;class Student { private String name; private int age; private float score; public Student(String name, int age, float score) { this.name = name; this.age = age; this.score = score; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public float getScore() { return score; } public void setScore(float score) { this.score = score; } public String toString() { return name+"\t\t"+age+"\t\t"+score; }}class StudentComparator implements Comparator<Student>{ public int compare(Student o1, Student o2) { if(o1.getScore()>o2.getScore()) return -1; else if(o1.getScore()<o2.getScore()) return 1; else{ if(o1.getAge()>o2.getAge()) return 1; else if(o1.getAge()<o2.getAge()) return -1; else return 0; } } }public class comparatorDemo1 { public static void main(String[] args) { Student stu[]={new Student("zhangsan",20,90.0f), new Student("lisi",22,90.0f), new Student("wangwu",20,99.0f), new Student("sunliu",22,100.0f)}; java.util.Arrays.sort(stu,new StudentComparator()); for(Student s:stu) { System.out.println(s); } }}
<span style="font-size:18px;">StudentComparator类完整地实现了整个排序应用的算法,所以它是策略模式</span>
策略模式和模版方法模式对比
1.两者的意图不同。策略模式的意图是定义一个算法家族,把每个算法封装起来并让这些算法可以互换,这样客户可以轻易使用不同的算法。模版方法模式的意图是在抽象类定义一个算法大纲,而由子类定义其中某些步骤的内容,算法的个别步骤可以有不同的实现细节而算法的结果始终维持不变,达到代码的复用效果。
2.实现方法不同。策略模式是通过对象组合的方式实现的,而模版方法模式是通过继承实现的
3.各种的优势不同。模版方法对算法有更多的控制权,它的类的效率会比策略高效,会重复使用到的代码,都被放进超类,好让所有的子类共享,这使得它经常被用于创建框架。策略模式使用对象组合,因此更有弹性,可以方便选择使用不同的算法,加入新的算法也很方便,不需要依赖超类中方法的实现
- 设计模式-模板方法模式 策略模式
- 设计模式之模板方法模式和策略模式
- 设计模式之模板方法模式和策略模式
- 策略模式&&模板方法模式
- 模板方法模式,策略模式
- Head First设计模式学习—模板方法、策略模式
- 设计模式之模板方法模式、策略模式、命令设计模式
- 设计模式:模板方法模式
- 设计模式 - 模板方法模式
- 设计模式:模板方法模式
- 设计模式 模板方法模式
- 设计模式--模板方法模式
- 设计模式-【模板方法模式】
- 设计模式: 模板方法模式
- 设计模式- 模板方法模式
- 设计模式 - 模板方法模式
- 设计模式 - 模板方法模式
- 设计模式-模板方法模式
- 类的本质Class
- 解决宿主机不能访问虚拟机Centos中的站点
- ACM第一个学期回顾
- 第十周项目4—— 类族的设计(1)
- May'English Learning
- 设计模式-模板方法模式 策略模式
- 慕课网深入浅出javascript
- 黑马程序员_Java(反射)
- JDBC
- load方法和initialize方法
- c函数返回数组
- process terminated with status 255 in codeblocks
- poj2386(dfs)
- VC设置鼠标光标的方式比较