目录
模板模式(Template Method):
举例
钩子函数(hook)-挂钩
模板设计模式/方法-总结
模板模式(Template Method):
定义一个 *** 作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
举例关于饮品的制作:
泡好的茶倒在顾客杯子中
加柠檬
1.一键启动按钮:即用这个方法,四个步骤直接就完了,饮料就直接出来了,并且这个方法不允许修改,子类只能使用不能修改。
2.当直接创建两个饮品类单独实现咖啡和红茶两个代码时存在问题:
观察代码:
public class Coffee { //一键启动按钮,点击能出一杯咖啡(包含所有制作流程) public void prepareRecipe(){ boilWater();//烧水 brewCoffeeBag();//泡咖啡 pourIncup();//泡好的咖啡倒入杯中 addSugarAndMilk();//加入糖和奶 } private void addSugarAndMilk() { System.out.println("adding sugar and milk"); } private void pourIncup() { System.out.println("pouring into cup"); } private void brewCoffeeBag() { System.out.println("brewing coffee bag"); } private void boilWater() { System.out.println("boiling water"); } }
public class Tea { public void prepareRecipe(){ boilWater();//烧水 steepTeaBag();//泡茶 pourIncup();//泡好的茶倒入杯中 addLemon();//加入柠檬 } private void addLemon() { System.out.println("adding lemon"); } private void pourIncup() { System.out.println("pouring into cup"); } private void steepTeaBag() { System.out.println("steeping tea bag"); } private void boilWater() { System.out.println("boiling water"); } }
1)如果分开编写咖啡,红茶等代码,会出现代码冗余,如烧水和倒入杯中这两个方法对于所有热饮都通用。
2)若要扩展新的热饮奶茶,会很不方便,代码中所有方法又得重写一遍,不方便扩展。
3)就顾客使用来说,得得知店里所有饮品才能点单
3.针对这种问题,提出了优化方案:
1)烧水和入杯对所有热饮通用--无论是咖啡还是茶,都含咖啡因->联想继承
2)则可把咖啡因饮料设计为一个父类CaffeineBeverage,Coffee extends CoffeineBeverage,Tea extends CoffeineBeverage。
3)烧水和倒入杯中 *** 作写到父类,子类可以直接使用(继承关系)。对于咖啡和茶来说,泡茶泡咖啡,加奶加柠檬就得具体子类实现,父类中无法实现,要延迟到具体子类中实现,这种方法就是用抽象方法实现。
4)对于饮品具体制作流程,对于顾客不可见。为了保证这个品牌所有饮品在不同门店味道都是相同的,就需要把制作流程prepareRecipe()封装到父类中,子类只能使用不能修改【用到关键字final:final修饰的方法子类不能覆写,只能使用不能修改】
代码实现:
public abstract class CaffeineBeverage { public final void prepareRecipe(){ boilWater();//烧水-父类实现 brew();//冲、泡,不同饮料不同冲泡方法-子类实现 pourIncup();//倒入杯子-父类实现 addCondiments();//加调味品,不同饮品添加不同调味品-具体到子类 } public abstract void brew(); public abstract void addCondiments(); private void pourIncup() { System.out.println("倒入杯中"); } private void boilWater() { System.out.println("烧水"); } }
public class Coffee extends CaffeineBeverage{ @Override public void brew() { System.out.println("把咖啡冲泡入水中"); } @Override public void addCondiments() { System.out.println("添加糖和牛奶"); } }
public class Tea extends CaffeineBeverage{ @Override public void brew() { System.out.println("把茶包浸泡水中"); } @Override public void addCondiments() { System.out.println("添加柠檬"); } }
4.总结:
1)子类只需关心独有的实现方法(子类只覆写抽象方法),共同的方法拿来用即可
2)父类封装了核心方法(算法),子类只能使用不能修改,对于核心方法来说就是一种保护
3)要扩展一个新的类非常容易,假设还要添加奶茶,直接继承父类饮料类,拓展不同方法即可
钩子函数(hook)-挂钩对于子类中可做可不做的事,如加调味品,有人加有人不加,这时就要用到hook
对于父类来说,是否加调味品是由子类来决定的,父类默认不改变原有方法(即执行默认 *** 作),子类覆写父类这个方法做相应代码实现。
父类中:
if(isCustomerWantsCondiments()){//若加(true),执行此步骤 addCondiments();//添加调味品 } public boolean isCustomerWantsCondiments(){//是否加调料 return true;//父类中默认加调料--子类可以选择不加,若不加,覆写子方法即可 }
子类中:
Scanner scanner=new Scanner(System.in);//获取一个系统输入询问顾客是否加 @Override//覆写了父类中的方法 public boolean isCustomerWantsCondiments() { System.out.println("您想加糖和牛奶吗?y is add,n is not add"); String str=scanner.nextLine(); if(str.equals("y")){//引用数据类型比较相等使用equals()方法 return true;//加返回true } return false; }模板设计模式/方法-总结
1.所谓的模板设计模式,它有一个模板方法,这个模板方法被声明为final封装在父类中,子类只能用不能改【相当于上面的prepareRecipe方法】
2.具体的 *** 作要延迟到子类中实现的,声明为抽象方法
3.共同都需要的方法,定义在父类中
4.钩子方法:默认不做事的方法,默认父类中返回true(即让本身默认继续加调味品)。子类可以视情况决定要不要覆盖它们【子类通过覆写,选择是否需要加调味品,需要加的话返回true,不需要加返回false】
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)