Java设计模式之模板方法模式

Java设计模式之模板方法模式

1.什么是模板方法模式(Template Method) 为算法的执行定义了一个统一的框架,其中的某些具体实现方法需要他在子类中去完成,每个子类所做的事情可能都不一样,而子类可以在不改变这个框架的同时去完成该算法的某个具体步骤,这就是我们所说的模板模式。

生活中的模板:

银行办理业务,1、进门取号 2、填写单据 3、等待叫号 4、窗口办理,对于这四个规则,所有
来办理业务的人都需要遵循这四种规则,但是在四个规则中规则2填写单据去是需要顾客填写的,
因为银行他并不知道顾客具体要办理什么样的业务,所以,他只能让顾客自己去填写这样的单据,
这样银行就是为顾客定义了一个模板。

2.如何实现模板方法模式

1.首先需要一个抽象基类,为所有子类提供一个算法框架  
2.定义一个模板方法,封装所有子类共同遵循的算法框架  
3.将对应的步奏写入模板方法中,将所有共同方法声明为私有的或者final方法,为了隐藏实现细节  
4.将所有并不知道具体实现什么的方法设置为抽象方法,为了让他的子类去实现具体细节  
5.所有子类的具体实现    

细节:钩子方法实现:加入一个判断条件,询问用户是否需要执行该操作,提供一个默认或空的实现,让子类去选择是否挂钩,
模板方法模式的实现要素:
准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性,最后将方法汇总构成一个不可改变的模板方法。

3.模板方法模式的特点

优点:封装性好,、复用性好、屏蔽细节、便于维护

缺点:继承的局限性

4.模板方法模式在项目中的应用

1.算法或操作遵循相似的逻辑  

2.重构时,把相同的代码抽取到父类中  

3.重要、复杂的算法,核心算法设计为模板算法  

下面就通过写一个银行办理业务的模板模式:

首先是一个抽象基类:

BankOption.java

    public abstract  class BankOption {

    protected String name;
    public BankOption(String name){
        this.name = name;
    }
    public void templete(){
        //1.办理业务
        business();
        //2.填写单据
        writeBills();
        //3.等待呼叫
        callWait();
        //4.窗口办理
        windowDeal();
    }

    /**
     * 办理业务
     */
    private   void business(){
        System.out.println(name + "办理业务");
    }

    /**
     * 填写单据,具体填写说明单据,让用户自己选择
     */
    protected abstract void writeBills();

    /**
     * 等待呼叫
     */
    private  void callWait(){
        System.out.println(name + "等待呼叫...");
        //模拟顾客等待5秒钟
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //5秒后等待结束,可以办理业务了
        System.out.println("呼叫" + name + "到窗口办理业务");
    }

    /**
     * 窗口办理
     */
    private   void windowDeal(){
        System.out.println(name + "窗口办理");
        System.out.println("窗口办理中...");
        //模拟在窗口办理业务时3秒钟
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + "办理业务完成");
    }

}

Customer1.java

    public class Customer1 extends BankOption{
    public Customer1(String name){
        super(name);
    }
    @Override
    protected void writeBills() {
        System.out.println(name + "填写汇款单据");
    }
}

Customer2.java

    public class Customer2 extends BankOption{
    public Customer2(String name){
        super(name);
    }
    @Override
    protected void writeBills() {
        System.out.println(name + "填写存款单据");
    }
}

Customer3.java

    public class Customer3 extends BankOption{
    public Customer3(String name){
        super(name);
    }
    @Override
    protected void writeBills() {
        System.out.println(name + "填写办理银行卡业务");
    }
}

Main.java测试类:

public class Main {
    public static void main(String[] args) {
        BankOption c1 = new Customer1("顾客1");
        BankOption c2 = new Customer2("顾客2");
        BankOption c3 = new Customer3("顾客3");
        c1.templete();
        System.out.println("\n*************************");
        c2.templete();
        System.out.println("*************************");
        c3.templete();

        }
    }

运行结果:
顾客1办理业务
顾客1填写汇款单据
顾客1等待呼叫…
呼叫顾客1到窗口办理业务
顾客1窗口办理
窗口办理中…
顾客1办理业务完成

***************

顾客2办理业务
顾客2填写存款单据
顾客2等待呼叫…
呼叫顾客2到窗口办理业务
顾客2窗口办理
窗口办理中…
顾客2办理业务完成

***************

顾客3办理业务
顾客3填写办理银行卡业务
顾客3等待呼叫…
呼叫顾客3到窗口办理业务
顾客3窗口办理
窗口办理中…
顾客3办理业务完成

上就是一个简单的银行办理业务的模板方法模式,我们把所以规定了的步奏,1、3、4都写在基类中,这样很好的隐藏了实现细节,顾客只需要填写对应的单据就行了,那么我们可以通过上面的例子再改进下,来理解下上面提到的细节:钩子方法,为什么使用钩子方法呢?上面我们每个用户都模拟了等待呼叫功能,有时候如果另外一个窗口已经是空闲的,就可以直接叫用户去办理业务了,这个时候我们就可以使用钩子方法了,当钩子方法钩上的时候,也就是在本程序中表示,你可以不用等待呼叫,直接去窗口办理业务了,如果没有钩上,就表示你要继续等待,这里就模拟一下,1、3不等待,2等待。通过一下代码比较一下。

BankOption.java中加入一个钩子方法即可

public void templete(){
        //1.办理业务
        business();
        //2.填写单据
        writeBills();
        //3.等待呼叫
        if(isWait())
            callWait();
        else
            System.out.println("不需要等待");
        //4.窗口办理
        windowDeal();
    }
    //通过加入这个方法去判断是否需要等待,当然,这里有点不符合实际,
    //因为这里是用户去实现是否等待,一般来说我们是银行来控制是否顾客等待,不过只要大家理解钩子方法是什么意思就可以了
    protected abstract boolean isWait();

然后每个用户去添加实现钩子方法即可:

Customer1.java

    @Override
    protected boolean isWait() {
        //false表示不需要等待,直接办理窗口
        return false;
    }

Customer2.java

     @Override
    protected boolean isWait() {
        //表示需要等待
        return true;
    }

Customer3.java

    @Override
    protected boolean isWait() {
        //不需要等待
        return false;
    }

运行结果:

顾客1办理业务
顾客1填写汇款单据
不需要等待
顾客1窗口办理
窗口办理中…
顾客1办理业务完成

***************
顾客2办理业务
顾客2填写存款单据
顾客2等待呼叫…
呼叫顾客2到窗口办理业务
顾客2窗口办理
窗口办理中…
顾客2办理业务完成

***************
顾客3办理业务
顾客3填写办理银行卡业务
不需要等待
顾客3窗口办理
窗口办理中…
顾客3办理业务完成

模板方法模式就介绍到这里,在我们的实际开发应用过程中,模板方法模式应用非常广泛,所以这种设计模式大家一定得掌握。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值