HeadFirst 设计模式学习之模板方法模式

HeadFirst 设计模式学习之模板方法模式

模板方法定义

在一个方法中定义一个算法骨架,而将一些步骤延迟到子类中,模板方
法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

demo演示–泡茶和冲咖啡

分析:

泡茶和冲咖啡都可以分成下面四个步骤:

  • 把水烧热
  • 冲泡茶/咖啡
  • 将茶/咖啡倒入杯子
  • 加入合适的调料(茶可以放柠檬,咖啡放糖)

    定义算法骨架:

        void preparRecipe()
    {
        boilWater();    //烧水
        brew();         //冲泡
        pourInCup();    //倒入杯子
        addCondiments();//加调料
    }
    

    上面的骨架中,咖啡和茶烧水喝倒入杯子的过程是完全相同的,所以定义在基类中,其他两个方法则有子类负责实现。

    基类

    abstract class Beverage {
    public final void preparRecipe()
    {
        boilWater();    //烧水
        brew();         //冲泡
        pourInCup();    //倒入杯子
        addCondiments();//加调料
    }
    
     public abstract void addCondiments();
    
    public void pourInCup() {
        // TODO Auto-generated method stub
        System.out.println("pourInCup-------");
    }
    
    public abstract void brew() ;
    
    public  void boilWater() {
        // TODO Auto-generated method stub
        System.out.println("BoilWater-------");
    }
    
    }
    

    子类Tea

    class Tea extends Beverage {
    
    @Override
    public void addCondiments() {
        // TODO Auto-generated method stub
        System.out.println("add Condiment to tea-------");
    }
    
    @Override
    public void brew() {
        // TODO Auto-generated method stub
        System.out.println("brew tea-------");
    }
    
    }
    

    咖啡类与茶类相似,代码就不再贴出。

    测试代码及结果:
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Tea().preparRecipe();
    }
    BoilWater-------
    brew tea-------
    pourInCup-------
    add Condiment to tea-------
    

再进一步,模板方法与钩子

在上一个部分中,我们定义了一个含有四个部分的算法骨架,其中两个部分交给子类去实现,另外两个由基类实现。这样做,对于基类来说,屏蔽了算法的某些细节,而子类负责实现这些细节,从而将自己挂载到算法当中去,而钩子则能够改变算法流程。

钩子的魅力——灵活的加入调料

先对上面的基类做出以下修改:

  • 加入方法getAns(),用来得到是否需要调料。
  • 将该方法放入preparRecipe()。

修改完的类:

abstract class Beverage {
public final void preparRecipe()
{
    boilWater();    //烧水
    brew();         //冲泡
    pourInCup();    //倒入杯子
    if(getAns())
    addCondiments();//加调料
}

 public abstract void addCondiments();

public void pourInCup() {
    // TODO Auto-generated method stub
    System.out.println("pourInCup-------");
}

public abstract void brew() ;

public  void boilWater() {
    // TODO Auto-generated method stub
    System.out.println("BoilWater-------");
}
public boolean getAns()
{
    return true; //默认是加调料的
}
}

Tea类复写方法getAns()

public boolean getAns() {
    // TODO Auto-generated method stub
    System.out.println("是否加入调料:(Y/N)");
    BufferedReader in=new BufferedReader(new InputStreamReader(System.in));
    try {
        if("Y".equals(in.readLine()))
        {
            return true;
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}

运行结果:

BoilWater-------
brew tea-------
pourInCup-------
是否加入调料:(Y/N)
Y
add Condiment to tea-------

上述过程中,子类通过复写了基类的方法来达到改变算法流程的目的(是否执行addCondiments()方法),这就是钩子的用法。

涉及的原则:好莱坞原则

好莱坞原则:别调用我们,我们会调用你。

好莱坞原则是防止“依赖腐败”(高层和低层相互依赖)的方法,它让高层决定流程(什么时候调用低层),低层决定某些细节。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值