周三,9:00,我刚刚坐到位置上,打开电脑准备开始干活。算法
“小三,小三,叫一下其余同事,到会议室,开会”,老大跑过来吼,带着坏笑。还没等你们坐稳,老大就开讲了:架构
“告诉你们一个好消息,昨天终于把牛叉模型公司的口子打开了,要咱们作悍马模型,虽然是第一个车辆模型,可是咱们有能力、有信心作好,咱们必定要……(中间省略20分钟的讲话,若是你听过领导人的讲话,这个你应该可以续上)”ide
动员工做作完了,那就开始压任务了。“此次时间是很是紧张的,只有一个星期的时间,小三,你负责在一个星期的时间把这批10万车模(注:车模是车辆模型的意思,不是香车美女那个车模)建设完成…”测试
“一个星期?这个……是真作不完,要作分析,作模板,作测试,还要考虑扩展性、稳定性、健壮性等,时间实在是太少了”还没等老大说完,我就急了,再不急个人小命就折在上面了!this
“那这样,只作最基本的实现,不考虑太多的问题,怎么样?”老大又把我弹回去了。spa
“只做基本实现?那……”设计
唉,领导已经布置任务了,那就开始死命地作吧,命苦不能怨政府,点背不能怪社会呀!而后就开始准备动手作,在作以前先介绍一下咱们公司的背景,咱们公司是作模型生产的,作过桥梁模型、建筑模型、机械模型,甚至是一些政府、军事的机密模型,这个不能细说,绝密。公司的主要业务就是把实物按照必定的比例缩小或放大,用于试验、分析、量化或者是销售,等等,上面提到的牛叉模型公司专门销售车辆模型的公司,本身没有生产企业,所有是代工。咱们公司是第一次从牛叉模型公司接单,那我怎么着也要把活干好,可时间有限,任务量又巨大,怎么办?code
既然领导都说了,不考虑扩展性,那好办,先按照最通常的经验设计类图,如图1-1所示blog
图1-1 悍马车模型最通常的类图继承
很是简单的实现,悍马车有两个型号,H1和H2,按照需求,只须要悍马模型,那好我就给你悍马模型,先写个抽象类,而后两个不一样型号的模型实现类,经过简单的继承就能够实现业务要求。咱们先从抽象类编写起,抽象悍马模型如代码清单10-1所示。
代码清单1-1 抽象悍马模型
public abstract class HanmaModel { public abstract void start(); public abstract void alarm(); public abstract void enginStart(); public abstract void run(); }
在抽象类中,咱们定义了悍马模型都必须具备的特质:可以启动、中止,喇叭会响,引擎能够轰鸣,并且还能够中止,可是每一个型号的悍马实现是不一样的,H1型号的悍马如代码清单1-2所示。
代码清单1-2 H1型号悍马模型
public class HanmaH1Model : HanmaModel { public override void start() { Console.WriteLine("悍马H1启动!"); } public override void alarm() { Console.WriteLine("悍马H1鸣笛!"); } public override void enginStart() { Console.WriteLine("悍马H1发动机发出声音!"); } public override void stop() { Console.WriteLine("悍马H1中止!"); } public override void run() { this.start(); this.alarm(); this.enginStart(); this.stop(); } }
你们注意看run()方法,这是一个汇总的方法,一个模型生产成功了,总要拿给客户检测吧,怎么检测,“是骡子是马,拉出去溜溜”,这就是一种检验方法,让它跑起来!经过run()这样的方法,把模型的全部功能都测试到了。
H2型号悍马如代码清单1-3所示。
代码清单1-3 H2型号悍马模型
public class HanmaH2Mode:HanmaModel { public override void start() { Console.WriteLine("悍马H2启动!"); } public override void alarm() { Console.WriteLine("悍马H2鸣笛!"); } public override void enginStart() { Console.WriteLine("悍马H2发动机发出声音!"); } public override void stop() { Console.WriteLine("悍马H2中止!"); } public override void run() { this.start(); this.alarm(); this.enginStart(); this.stop(); } }
好了,程序编写到这里,已经发现问题了,两个实现类的run()方法都是彻底相同的,那这个run()方法的实现应该出如今抽象类,不该该在实现类上,抽象是全部子类的共性封装。
注意 在软件开发过程当中,若是相同的一段代码拷贝过两次,就须要对设计产生怀疑,架构师要明确的说明为何相同的逻辑要出现两次或更屡次。
好,问题发现了,咱们就须要立刻更改,修改后的类图如图1-2所示。
图1-2 修正后的悍马车模类图
注意抽象类HummerModel中的run()方法,由抽象方法变动为实现方法,其源代码如代码清单10-4所示。
代码清单1-4 修正后的抽象悍马模型
public abstract class HanmaModel { public abstract void start(); public abstract void alarm(); public abstract void enginStart(); public abstract void stop(); public void run() { this.start(); this.alarm(); this.enginStart(); this.stop(); } }
在抽象的悍马模型上已经定义了run方法的执行规则,先启动,而后引擎马上轰鸣,中间还要按一下喇叭,制造点噪声(要不就不是名车了),而后停车,它的两个具体实现类就不须要实现run方法了,只要把代码清单1-二、1-3上的run()方法删除便可,再也不赘述代码。
public class HanmaH2:HanmaModel { public override void start() { Console.WriteLine("悍马H2启动!"); } public override void alarm() { Console.WriteLine("悍马H2鸣笛!"); } public override void enginStart() { Console.WriteLine("悍马H2发动机发出声音!"); } public override void stop() { Console.WriteLine("悍马H2中止!"); } } public class HanmaH1:HanmaModel { public override void start() { Console.WriteLine("悍马H1启动!"); } public override void alarm() { Console.WriteLine("悍马H1鸣笛!"); } public override void enginStart() { Console.WriteLine("悍马H1发动机发出声音!"); } public override void stop() { Console.WriteLine("悍马H1中止!"); } }
场景类实现的任务就是把生产出的模型展示给客户,其源代码如代码清单10-5所示。
代码清单1-5 场景类
class Program { static void Main(string[] args) { HanmaH1 h1 =new HanmaH1(); h1.run(); HanmaH2 h2 = new HanmaH2(); h2.run(); Console.ReadLine(); } }
模板方法模式(Template Method Pattern)是如此的easy,以至让你感受你已经可以掌握其精髓了。其定义以下:
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure。定义一个操做中的算法的骨架,而将一些步骤延迟到子类中。使得子类能够不改变一个算法的结构便可重定义该算法的某些特定步骤。
模板方法模式的通用类图如图1-3所示。
图1-3 修正后的悍马车模类图
模板方法模式确实很是简单,仅仅使用了Java的继承机制,可是它是一个应用很是普遍的模式。其中,AbstractClass叫作抽象模板,它的方法分为两类:
基本方法也叫作基本操做,是由子类实现的方法,而且在模板方法被调用。
能够有一个或几个,通常是一个具体方法,也就是一个骨架,实现对基本方法的调度,完成固定的逻辑。
注意为了防止恶意的操做,通常模板方法都加上final关键字,不容许被覆写。