模板方法模式

来源:互联网 发布:次声波软件 编辑:程序博客网 时间:2024/05/21 19:21

  工厂生产出来的汽车都要经过试驾测试,通过测试才能销售市场,下面我们来模拟汽车试驾过程,假设我们现在只试驾奥迪A6和奥迪A8,示例代码如下:
  
抽象奥迪车(AudiCar):

public abstract class AudiCar{    //发动,测试发动机    public  abstract void start();    //按喇叭,测试喇叭    public abstract void alarm();    //起步,出发,走起    public abstract void run();    //刹车,下车测试完毕    public abstract void stop();}

测试的奥迪的具体车型奥迪A8(AudiA8):

public class AudiA8Car extends AudiCar{    @Override    public void start()    {        // TODO Auto-generated method stub        System.out.println("奥迪A8发动");    }    @Override    public void alarm()    {        // TODO Auto-generated method stub        System.out.println("奥迪A8哔哔哔");    }    @Override    public void run()    {        // TODO Auto-generated method stub        this.start();//启动        this.alarm();//前方遇到人了按喇叭        this.stop();//到达目的地停车    }    @Override    public void stop()    {        // TODO Auto-generated method stub        System.out.println("奥迪A8到达目的地,下车");    }}

测试的奥迪的具体车型奥迪A6(AudiA6):

public class AudiA6Car extends AudiCar{    @Override    public void start()    {        // TODO Auto-generated method stub        System.out.println("奥迪A6发动");    }    @Override    public void alarm()    {        // TODO Auto-generated method stub        System.out.println("奥迪A6哔哔哔");    }    @Override    public void run()    {        // TODO Auto-generated method stub        this.start();//启动        this.alarm();//前方遇到人了按喇叭        this.stop();//到达目的地停车    }    @Override    public void stop()    {        // TODO Auto-generated method stub        System.out.println("奥迪A6到达目的地,下车");    }}

测试类(AudiTest):

public class AudiTest{    public static void main(String[] args)    {        AudiCar  audiA6 = new AudiA6Car();        audiA6.run();        AudiCar  audiA8 = new AudiA8Car();        audiA8.run();    }}

试驾结果:

奥迪A6发动奥迪A6哔哔哔奥迪A6到达目的地,下车奥迪A8发动奥迪A8哔哔哔奥迪A8到达目的地,下车

  奥迪车试驾过程完成了,发现问题在两个类里面的run()方法代码都是完全相同的,我们应该把这段重复的代码放在抽象类中,在日常软件开发过程中如果一段代码发生了多次复制,我们就应该怀疑设计是否出了问题。下面我们对代码进行如下修改:
  
抽象奥迪车(AudiCar):把重复的代码放在抽象类里

public abstract class AudiCar{    //发动,测试发动机    public  abstract void start();    //按喇叭,测试喇叭    public abstract void alarm();    //起步,出发,走起    public  void run()    {        this.start();//启动        this.alarm();//前方遇到人了按喇叭        this.stop();//到达目的地停车    }    //刹车,下车测试完毕    public abstract void stop();}

测试的奥迪的具体车型奥迪A8(AudiA8):

public class AudiA8Car extends AudiCar{    @Override    public void start()    {        // TODO Auto-generated method stub        System.out.println("奥迪A8发动");    }    @Override    public void alarm()    {        // TODO Auto-generated method stub        System.out.println("奥迪A8哔哔哔");    }    @Override    public void stop()    {        // TODO Auto-generated method stub        System.out.println("奥迪A8到达目的地,下车");    }}

测试的奥迪的具体车型奥迪A6(AudiA6):

public class AudiA6Car extends AudiCar{    @Override    public void start()    {        // TODO Auto-generated method stub        System.out.println("奥迪A6发动");    }    @Override    public void alarm()    {        // TODO Auto-generated method stub        System.out.println("奥迪A6哔哔哔");    }    @Override    public void stop()    {        // TODO Auto-generated method stub        System.out.println("奥迪A6到达目的地,下车");    }}

测试类(AudiTest):

public class AudiTest{    public static void main(String[] args)    {        AudiCar  audiA6 = new AudiA6Car();        audiA6.run();        AudiCar  audiA8 = new AudiA8Car();        audiA8.run();    }}

试驾结果:

奥迪A6发动奥迪A6哔哔哔奥迪A6到达目的地,下车奥迪A8发动奥迪A8哔哔哔奥迪A8到达目的地,下车

  修改过后代码就是模板方法模式。
模板方法模式定义:
  Define the skeleton of an algorithm in an operation, deferring some steps to subclass. Template Method lets subclasses redefine certain of n algorithm without changing the algorithm’s structure.(定义一个操作中的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤)
  模板方法模式确实非常简单,仅仅使用了java继承机制,其中AbstractClass叫做抽象模板,他的方法分为基本方法、模板方法和钩子方法。
  基本方法:由子类实现,并且由模板方法调用(如上述的start(),alarm(),stop()方法)。
  模板方法:可以有一个或者几个,一般是一个具体方法,也是一个框架,实现基本方法的调度,完成固定的逻辑,通常为了不让模板方法被修改需添加final修饰。
   钩子方法:在模板方法模式中,钩子方法可以与一些具体步骤“挂钩”,以实现在不同条件下执行模板方法中的不同步骤,这类钩子方法的返回类型通常是boolean类型的,这类方法名一般为IsXXX(),用于对某个条件进行判断,如果条件满足则执行某一步骤,否则将不执行,如下代码片段所示:

public abstract class AudiCar{    //发动,测试发动机    public  abstract void start();    //按喇叭,测试喇叭    public abstract void alarm();    //起步,出发,走起    public  void run()    {        this.start();//启动        if(isAlarm())        {            this.alarm();//前方遇到人了按喇叭        }        this.stop();//到达目的地停车    }    //刹车,下车测试完毕    public abstract void stop();    //钩子方法,默认喇叭是会响的    protected boolean isAlarm()    {        return true;    }}

  在代码中isAlarm()方法即是钩子方法,它可以决定alarm()方法是否执行,一般情况下,钩子方法的返回值为true,如果不希望某方法执行,可以在其子类中覆盖钩子方法,将其返回值改为false即可,这种类型的钩子方法可以控制方法的执行,对一个算法进行约束。
  
模板方法的优点:
  封装不变部分,扩展可变部分
  提取公共部分的代码,便于维护
  行为由父类控制,子类实现
模板方法的缺点:
   每一个不同的实现都需要一个子类来实现,导致类的个数增加,是的系统更加庞大。

0 0