浅析设计模式之六 模板方法模式

 template method pattern
一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.
模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤
 
疑问:
    问:创建一个模板方法时,什么时候用抽象方法?什么时候用钩子
    答:当你的子类"必须"提供算法中的某个算法或者步骤的实现时,就使用抽象方法
         如果算法的这个部分是可选的,就用钩子
         如果是钩子的话,子类可以实现这个钩子,但并不强制这么做
 
    问:钩子的真正目的
    答:1.钩子可以让子类实现算法中可选的部分    钩子对于子类的实现并不重要,子类可以对钩子置之不理
         2.让子类能够有机会对模板方法中某些即将发生的(或者刚刚发生的)步骤做出反应            
         3.钩子也可以让子类有能力为其抽象类做一些决定
 
好莱坞原则:
     别调用我们,我们会调用你
    防止依赖腐败
     依赖腐败: 高层组件依赖底层组件,底层组件依赖高层组件,高层组件依赖边侧组件,边侧组件又依赖底层组件,
    在好莱坞依赖原则下,允许底层组件将自己挂钩到系统上(IOC就是基于此原则)
/**
 * 咖啡因饮料
 * @author Dougest
 * 2017年7月4日   下午1:49:52
 *
 */
public abstract class CaffeineBeverageWithHook {
    void prepareRecipe() {
        boilWater();
        brew();//冲泡
        pourInCup();
        if(customerWantsCondiments())//钩子
            addCondiments();//调料
    }
    
    abstract void brew();
    
    abstract void addCondiments();
    
    void boilWater(){
        int j = 20;
        System.out.println("烧水....");
        for(int i = 20; i < 100;i++) {
            j+=1;
            System.out.println("水温: "+(j)+" 度");
        }
        System.out.println("水开了");
    }
    
    void pourInCup() {
        System.out.println("到入杯子");
    }
    
    boolean customerWantsCondiments() {
        return true;
    }
}
/**
 * 咖啡
 * @author Dougest
 * 2017年7月4日   下午1:57:17
 *
 */
public class CoffeeWithHook extends CaffeineBeverageWithHook{
    void brew() {
        System.out.println("过滤并倒入该咖啡");
    }
    void addCondiments() {
        System.out.println("加糖和牛奶");
    }
    
    /*****************************使用钩子************************************************/
    boolean customerWantsCondiments() {
        String answer = userInput();
        return answer.toLowerCase().startsWith("y");
    }
    
    private String userInput() {
        String answer = null;
        System.out.println("Would you like milk and sugar with your coffee (y/n)");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        try{
            answer = in.readLine();
        } catch(Exception e) {
            e.printStackTrace();
        }
        if(answer == null) 
            return "no";
        
        return answer;
    }
}
public class TeaWithHook extends CaffeineBeverageWithHook{
    @Override
    void brew() {
        System.out.println("放茶叶");
        
    }
    @Override
    void addCondiments() {
        System.out.println("加糖吗");
    }
    boolean customerWantsCondiments() {
        String answer = userInput();
        return answer.toLowerCase().startsWith("y");
    }
    
    private String userInput() {
        String answer = null;
        System.out.println("Would you like some sugar with your tea (y/n)");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        try{
            answer = in.readLine();
        } catch(Exception e) {
            e.printStackTrace();
        }
        if(answer == null) 
            return "no";
        
        return answer;
    }
}
public class MainTest {
    public static void main(String[] args) {
        CoffeeWithHook ch = new CoffeeWithHook();
        ch.prepareRecipe();
        
        TeaWithHook th = new TeaWithHook();
        th.prepareRecipe();
        
        
    }
}
在上面的代码中,咖啡因饮料是高层组件,咖啡和茶是底层组件
高层组件控制冲泡的算法,只需要子类在实现某个方法时,才调用子类
 
底层组件简单的提供一些实现细节 
好莱坞原则和依赖倒置原则:
依赖倒置原则教我们尽量避免使用具体类,多使用抽象
好莱坞原则是用在创建框架或者组件上的一种技巧,好让底层组件能够被挂钩进计算中,而有不会被高层组件依赖底层组件
两者的目标都是为了解耦,但是依赖倒置原则更加注重如何在设计中避免依赖
好莱坞原则教我们一个技巧,创建一个有弹性的设计,允许底层结构能够互相操作,又防止其他类太过依赖他们
 
底层组件在结束时,常常会调用高层组件中继承来的方法
我们要做的是,尽量避免高低层组件之间明显的环状依赖
 
模板方法是一个很常见的设计模式,对于框架来说;
框架控制如何做事情,由用户指定框架的算法中的每一个步骤的细节
 
 
异同点:
 
模板方法:
    1) 定义一个算法的大纲,子类定义某些步骤的内容  算法的不同步骤可以有不同的实现细节,但是算法的结构依然保持不变
    2)继承,子类共享重复算法
策略:
    1)放弃对算法的控制
    2)使用委托,因为对象组合,更有弹性
 
 
要点:
定义了算法步骤,把这些步骤延迟到子类
提供了代码复用的一个重要技能
抽象类可以定义具体方法,抽象方法和钩子
抽象方法有子类实现
钩子是一种抽象方法,他在抽象类中不做任何事或者只做默认的事,子类可以选择要不要覆盖他
为了防止子类更改父类中的算法,可以将超类算法用final修饰
好莱坞原则告诉我们,将决策权放在高层模块中,一边决定如何以及何时调用底层模块
策略模式和模板方法都是用来封装算法,不同的是一个是组合,一个是继承
工厂方法是模板方法的一个特殊版本
 

转载于:https://www.cnblogs.com/dougest/p/7143473.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值