博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java模板设计模式
阅读量:4626 次
发布时间:2019-06-09

本文共 2905 字,大约阅读时间需要 9 分钟。

1、概述

    模板设计模式定义:定义一个操作中的算法骨架,将步骤延迟到子类中。

    模板设计模式是一种行为设计模式,一般是准备一个抽象类,将部分逻辑以具体方法或者具体的构造函数实现,然后声明一些抽象方法,这样可以强制子类实现剩余的逻辑。不同的子类以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板设计模式能达成的功能。

    适用于一些复杂操作进行步骤分割、抽取公共部分由抽象父类实现、将不同的部分在父类中定义抽象实现、而将具体实现过程由子类完成。对于整体步骤很固定,但是某些部分易变,可以将易变的部分抽取出来,供子类实现。

    角色:

        抽象类:实现模板方法、定义算法骨架

        具体类:实现抽象类中的抽象方法,完成特定的算法

2、代码示例

    我们举一个比较常见的例子:将一个物品装进冰箱。为了达到这个目的我们一般有如下几步:

        a:打开冰箱门

        b:将物品装进冰箱

        c:关上冰箱门

    上面的这三步其实就是“将一个物品装进冰箱”这个算法的骨架。在这个算法中,物品这个字眼很重要,它是抽象的,而不是具体的,对于每个不同的物品,装入的时候行为可能不同,这一点非常重要。比如:

        a:将一块猪肉放进冰箱--->一块猪肉这么小,直接放进去

        b:将一头大象放进冰箱--->一头大象这么大,切碎放进去

    上面只是不恰当的举个例子,只是为了说明:针对与不同物品,放入冰箱的动作(行为)不同。

    特别注意:上面物品虽是抽象的,但是我最终想表达的是“将物品装进冰箱”这个行为是抽象的。

package com.yefengyu.pattern.template;public abstract class AbstractClass{    public final void execute()    {        open();        put();        close();    }    private void open()    {        System.out.println("打开冰箱");    }    private void close()    {        System.out.println("关闭冰箱");    }    protected abstract void put();}
 

    上面的AbstractClass类中的execute方法就是一个算法骨架,它定义了复杂操作的许多步骤,其中需要注意:

    (1)AbstractClass是抽象类,因为子类需要继承某些抽象方法

    (2)execute是算法骨架,让外部调用,所以必须是public,但是又不想让子类进行重写,因此使用final关键字,如果重写则导致整个流程混乱。

    (3)open和close方法是固定的步骤,定义为私有,不让子类修改。

    (4)put方法是protected 的,保证子类可以重写,但是其它类无法看到,又是abstract 则子类必须重写。因为父类AbstractClass无法得知具体的物品该如何放入冰箱,只有靠子类去实现了。

    下面来实现两个子类。

package com.yefengyu.pattern.template;public class Pork extends AbstractClass{    @Override    protected void put()    {        System.out.println("将一块猪肉装进冰箱:直接装啊");    }}
package com.yefengyu.pattern.template;public class Elephant extends AbstractClass{    @Override    protected void put()    {        System.out.println("将大象装入冰箱:你必须剁碎再装入");    }}

    这两个子类虽然在put中都只打印了一句话,但是我们可以想象这里的操作十分复杂,并且流程大不一样。下面我们来实现客户端代码。

package com.yefengyu.pattern.template;public class Client{    public static void main(String[] args)    {        AbstractClass abstractClass = new Pork();        abstractClass.execute();        System.out.println("-------------------");        abstractClass = new Elephant();        abstractClass.execute();    }}

    运行结果如下

    通过上面的例子,我么可以看出:不同的实现类,重写的抽象方法的逻辑不同,导致算法执行的结果也不相同,但是算法骨架是没有改变的。


3、案例剖析

    大家应该使用Thread类,在学习的时候,一定都注意到这个问题,我们重写了run方法,但是线程启动的时候,为什么使用start方法?

package com.yefengyu.pattern.template;public class MyThread{    public static void main(String[] args)    {        Thread thread = new Thread(){            @Override            public void run()            {                System.out.println("###");            }        };                thread.start();    }}

    其实Thread类也使用了模板设计模式,只是有些地方有些差异。

    总结:

    start方法就是算法骨架的入口,它定义算法的骨架;start0()方法是本地方法,该方法最终还是调用了Thread的run方法,具体细节不做介绍。那么我们可以简单的认为start0()就是run方法,那么这就和模板设计模式非常相似:

    start方法:算法框架入口和骨架,和上面的AbstractClass的execute方法对应。

    start0方法:可以看作run方法,虽然run方法不是抽象方法,但是也可以复写,并且一般必须复写,不然线程没啥业务,有啥意义呢?

    Thread线程的使用start启动,做了很多其它的事情,也在某个地方调用了run方法,它是线程完整执行的入口,就和上面的AbstractClass的execute方法一样;如果线程调用run方法启动,只是和普通方法调用一样,无法真正启动一个线程。

 

转载于:https://www.cnblogs.com/yefengyu/p/10520531.html

你可能感兴趣的文章
TEA加密算法java版
查看>>
Spring回调方法DisposableBean接口
查看>>
理解线性稳压器及其主要性能参数
查看>>
【线性代数】7-3:对角化和伪逆(Diagonalization and the Pseudoinverse)
查看>>
javascript _call3_实现继承
查看>>
android studio gradle结构项目引入本地代码
查看>>
滑动窗口
查看>>
【lydsy1407】拓展欧几里得求解不定方程+同余方程
查看>>
linux命令,个人的日记本
查看>>
YTU 1439: 2.4.5 Fractions to Decimals 分数化小数
查看>>
Zend Studio 10 汉化——离线语言包安装步骤
查看>>
epoll精髓
查看>>
Java Logging API - Tutorial
查看>>
secureCRT修改背景色、字体颜色
查看>>
仿写Windows7桌面和任务栏 HTML5+CSS3+Jquery实现
查看>>
zzuli oj 1146 吃糖果
查看>>
Your development team, "", does not support the Push Notifications capability.
查看>>
使用Safari浏览器调试WebView
查看>>
listview
查看>>
文字和图片垂直居中
查看>>