面向对象,是对事物属性与行为的封装,方法,指的就是行为。模板方法,显而易见是说某个方法充当了模板的作用,其充分利用了抽象类虚实结合的特性,虚部抽象预留,实部固定延续,以达到将某种固有行为延续至子类的目的。反观接口,则达不到这种目的。要搞明白模板方法,首先我们从接口与抽象类的区别切入,这也是面试官经常会问到的问题。

汽车上的接口最常见的就是这几个了,点烟器,USB,AUX等等,很明显这些都是接口,它们都预留了某种标准,暴露在系统外部,并与外设对接。就拿点烟器接口来说吧,它原本是专门用于给点烟器供电的,后来由于这个接口在汽车上的通用性,于是衍生出了各种外部设备,只要是符合这个标准size的,带正负极簧片的,直流12V的,那就可以使用,比如导航、行车记录仪、吸尘器什么的,以及其他各种车载电子设备。

public interface CigarLighterInterface {//点烟器接口//供电方法,16V直流电public void electrifyDC16V();
}
1 public class GPS implements CigarLighterInterface {
2    //导航的实现
3    @Override
4    public void electrifyDC16V() {
5        System.out.println("连接卫星");
6        System.out.println("定位。。。");
7    }
8
9 }1 public class CigarLighter implements CigarLighterInterface {2    //点烟器的实现3    @Override4    public void electrifyDC16V() {5        int time = 1000;6        while(--time>0){7            System.out.println("加热电炉丝");8        }9        System.out.println("点烟器弹出");
10    }
11
12 }

对于点烟器接口来说,它根本不在乎也不知道对接的外设是什么鬼,它只是定义了一种规范,一种标准,只要符合的都可以对接。再比如USB接口的应用更加广泛,外设更是应有尽有,具体例子可以参考文章《设计模式是什么鬼(初探)》。

以上我们可以体会到接口的抽象是淋漓尽致的,实现是空无的,也就是说其方法都是无实现的。然而这样在某些场景下会存在一些问题,例如有时候我们在父类中只需抽象出一些方法,并且同时也有一些实体方法,以供子类直接继承,这怎么办?答案就是抽象类。举个例子,哺乳动物类,我们人类就是哺乳动物。

什么?鲸鱼是哺乳类?是的,凡是喂奶的都是哺乳类,不要以为会游泳的都是鱼,会飞的都是鸟,蝙蝠同样是哺乳类,只不过是老鼠中的飞行员而已。

既然如此这哺乳动物肯定是都能喂奶了,但是到底是跑还是游,或是飞呢还真不好说,但至少可以确认它们都是可以移动的。言归正传,我们开始定义哺乳动物抽象类。

 1 public abstract class Mammal {23    //既然是哺乳动物当然会喂奶了,但这里约束为只能母的喂奶4    protected final void feedMilk(){5        if(female){//如果是母的……6            System.out.println("喂奶");7        }else{//如果是公的……或者可以抛个异常出去。8            System.out.println("公的不会");9        }
10    }
11
12    //哺乳动物当然可以移动,但具体怎么移动还不知道。
13    public abstract void move();
14 }

这里我们省略了female属性,其作用是为了控制喂奶行为,大家可以自行添加。可以看到的是,抽象类不同于接口,其自身是可以有具体实现的,也就是说抽象类是虚实结合的,虚部抽象行为,实部遗传给子类,虚虚实实,飘忽不定。OK,我们看下人、鲸、蝠的子类实现。

public class Human extends Mammal {@Overridepublic void move() {System.out.println("两条腿走路……");}}
public class Whale extends Mammal {@Overridepublic void move() {System.out.println("游泳……");}}
public class Bat extends Mammal {@Overridepublic void move() {System.out.println("用翅膀飞……");}}

可以看到子类的各路实现都是自己独有的行为方式,而喂奶那个行为是不需要自己实现的,它是属于抽象哺乳类的共有行为,哺乳子类不能进行任何干涉。这便是接口与抽象的最大区别了,接口是虚的,抽象类可以有虚有实,接口不在乎实现类是什么,抽象类会延续其基因给子类。

其实到这里我们已经说了一大半了,理解了以上部分,剩下的部分就非常简单了,利用抽象类的这个特性,便有了“模板方法”。举例说明,我们做软件项目管理,按瀑布式简单来讲分为:需求分析、设计、编码、测试、发布,先不管是用何种方式去实现各个细节,我们就抽象成这五个步骤。

public abstract class PM {protected abstract void analyze();//需求分析protected abstract void design();//设计protected abstract void develop();//开发protected abstract boolean test();//测试protected abstract void release();//发布
}

那么问题来了,有个程序员在需求不明确或者设计不完善的情况下,一上来二话不说直接写代码,这样就会造成资源的浪费,后期改动太大还会影响项目进度。那么项目经理这时就应该规范一下这个任务流程,这里我们加入kickoff()方法实现。

 1 public abstract class PM {2    protected abstract void analyze();//需求分析3    protected abstract void design();//设计4    protected abstract void develop();//开发5    protected abstract boolean test();//测试6    protected abstract void release();//发布78    protected final void kickoff(){9        analyze();
10        design();
11        develop();
12        test();
13        release();
14    }
15 }

这样就限制了整个项目周期的任务流程,注意这里要用final声明此方法子类不可以重写,只能乖乖的继承下去用。至于其他的抽象方法,子类可以自由发挥,比如测试方法test(),子类可以用人工测试,自动化测试,我们不care,我们是站在项目管理的抽象高度,只把控流程进度。这里甚至我们还可以加入一些逻辑如下。

 1 public abstract class PM {2    protected abstract void analyze();//需求分析3    protected abstract void design();//设计4    protected abstract void develop();//开发5    protected abstract boolean test();//测试6    protected abstract void release();//发布78    protected final void kickoff(){9        analyze();
10        design();
11        do {
12            develop();
13        } while (!test());//如果测试失败,则继续开发改Bug。
14        release();
15    }
16 }

以下子类只需实现抽象方法,而不用实现固有的模板方法kickoff(),因为它已经被父类PM实现了,并且子类也不能进行重写。

1 public class AutoTestPM extends PM{
2
3    @Override
4    protected void analyze() {
5        System.out.println("进行业务沟通,需求分析");
6    }
7
8    //design();develop();test();release();实现省略
9 }

至此,我们的模板方法就完成了,抽象类PM中的实方法kickoff()中,以某种逻辑编排调用了其他各个抽象方法,提供了一种固定模式的行为方式或是指导方针,以此达到虚实结合、柔中带刚、刚柔并济,灵活中不失规范的目的。

当然大部分情况我们使用接口会多于抽象类,因为接口灵活啊,抽象类不允许多继承啊等等,其实我们还是要看应用场景,在某种无规矩不成方圆,或者规范比较明确,的情况下抽象类的应用是有必要的,世间万物没有最好的,只有最合适的。

JAVA设计模式什么鬼(模板方法)——作者:凸凹里歐相关推荐

  1. JAVA设计模式什么鬼(备忘录)——作者:凸凹里歐

    备忘录,备份曾经发生过的历史记录,以防忘记,之后便可以轻松回溯过往.想必我们曾经都干过很多蠢事导致糟糕的结果,当后悔莫及的时候已经是覆水难收了,只可惜这世界上没有后悔药,事后我们能做的只能去弥补过失, ...

  2. JAVA设计模式什么鬼(策略)——作者:凸凹里歐

    策略,Strategy,古时也称"计",为了达成某个目标的方案,目标不同,方案也随之更改.例如特工执行任务时总要准备好几套方案以应对突如其来的变化,A计划实施过程中情况突变导致预案 ...

  3. JAVA设计模式什么鬼(状态)——作者:凸凹里歐

    状态State,指某事物所处的状况或形态,比如水的三态,零下会变成固态冰,常温会是液态水,100℃会蒸发成气态的水蒸气. 在这个地球生态系统中,水的总量并不会增加,也不会减少,只是随着温度的变化其分子 ...

  4. JAVA设计模式什么鬼(代理)——作者:凸凹里歐

    代理,代表打理,以他人的名义代表委托人打理其本职工作之外或不所能及的事务,达成合作关系并更高效地促成事务完成的目的.例如明星经纪人,他们并没有像明星一样会唱歌.跳舞或演戏,而是替明星打理一些无暇顾及的 ...

  5. JAVA设计模式什么鬼(初探)——作者:凸凹里歐

    有物混成,先天地生.寂兮寥兮,独立而不改,周行而不殆,可以为天地母.吾不知其名,字之曰道,强为之名曰大.大曰逝,逝曰远,远曰反. 道是什么?道可道,非常道.道不明,说不尽的才算是道,它是自然法则的终极 ...

  6. JAVA设计模式什么鬼(适配器)——作者:凸凹里歐

    我们这个世界,充满着千奇百怪的对象,更有趣的是对象与对象间是存在着互动,沟通,这样世界才变得美妙.那到底是怎样互动呢?靠什么才能互动呢?是的,接口.比如你和朋友一起喝茶聊天,我们暂且不管声带,耳膜这些 ...

  7. JAVA设计模式什么鬼(装饰)——作者:凸凹里歐

    装饰,在某物件基础上加以修饰,装点,使得原本的朴素变得华丽,达到化腐朽为神奇的效果.比如我们从开发商买来的毛坯房,必然要进行室内装潢这么一项工程,什么简约风啊,北欧风啊,地中海,美式中式等等,当然萝卜 ...

  8. JAVA设计模式什么鬼(门面)——作者:凸凹里歐

    开门见山,门,建筑物的入口,面,脸也.门面(Facade),通常指店铺的门头外表部分,当然一定要临街才是好的商铺,在人流量大的地方营造更好的视觉冲击,这样会有更多等等机会暴露给潜在顾客,否则只能是靠& ...

  9. JAVA设计模式什么鬼(中介)——作者:凸凹里歐

    中介,作用于多个事物之间充当交互沟通的媒介.我们的生活中有各种各样的媒介,比如一些传统媒体,书刊杂志,报纸,把信息传递给读者.再比如利用电子信息技术的互联网,作为一种新媒体,不单可以更高效地把信息传递 ...

最新文章

  1. MQTT:物联网的神经系统
  2. DoS Deflate Iptables
  3. libtorch 调用pytorch模型
  4. xml文件上传服务器读取不了,本地读取服务器Xml文件及本地读本地的xml
  5. 今天学了瀑布流的js方法
  6. NumPy常用属性及方法
  7. 如何去学会黑客技术,黑客电脑技术学习必备知识
  8. 3d数学基础:图形和游戏开发(第2版)_游戏引擎编程需要哪些基本数学知识?
  9. 一个项目的简单开发流程——需求、数据库、编码
  10. Futter基础第15篇: 实现类似闲鱼App底部导航凸起按钮
  11. 我Web前端开发的开端
  12. 节俭,是一种了不起的能力
  13. 这么多技术我该怎么学 杨中科
  14. switchhost 提示没有权限
  15. excel设置行高_聊聊python 办公自动化之 Excel(下)
  16. 认真学习设计模式之适配器模式(Adapter Pattern)/包装器模式
  17. 鸿蒙OS内核分析|解读鸿蒙源码
  18. 藏书馆App基于Rainbond实现云原生DevOps的实践
  19. 物理机安装linux系统失败,物理机(服务器)安装centos6.5 无法启动报Error loading operating--(示例代码)...
  20. 「MoreThanJava」一文了解二进制和CPU工作原理

热门文章

  1. 关于@Valid和Validated的比较
  2. 梦想成真---jdk版本的选择(推荐1.8)
  3. selenium和chrome版本不一致 session not created: This version of ChromeDriver only supports Chrome version
  4. java 三层架构_java三层架构详解
  5. rock64安装docker
  6. ubuntu 12.04 给四个工作区设置不同壁纸
  7. linux vim安装molokai配色方案
  8. 测绘程序设计——坐标正反算(C#)
  9. 体育场馆使用会员管理系统的好处有哪些
  10. 【毒思】纪念我死去的爱情