23种设计模式之 : 模板方法设计模式

每博一文案

青年,青年!无论受怎样的挫折和打击,都要咬着牙关挺住,因为你们完全有机会重建生活;只要不灰心丧气,每一次挫折就只不过是通往新境界的一块普通绊脚石,而绝不会置人于死命。昨天很辛苦,今天很残酷,明天很美好,大部分人撑不到明天。缘来缘去自由定数,知足常乐才是福。就以为如此,你也应该重新走向生活!二十七年来你付出的太少,不值得接受生活如此的馈赠。多大的痛苦也不能打乱日常的生活节拍————这就是他精神强大等我根本所在。黄河水总有清的一天,人不能穷一辈子!平凡的世界,质朴的人儿,渺小的心灵,然而无穷尽的对生活的热爱。只有劳动才可能使人在生活中强大。不论什么人,最终还是要崇尚那些能用双手创造生活的劳动者。活在这世界上,有人爱你,总不是一件坏事。命运总是不如人愿。但往往是在无数的痛苦中,在重重的矛盾和艰辛中,才是人成熟起来。                                           ——————  《平凡的世界》 路遥

@

目录

  • 23种设计模式之 : 模板方法设计模式
    • 每博一文案
    • 1. 23种设计模式之:模板方法 概述
      • 1.2 开闭原则
      • 1.3 里氏替换原则
      • 1.4 什么是模板方法设计模式
    • 2. 模板方法设计模式实例
      • 2.1 未用模板方法设计模式的处理
      • 2.2 用了模板方法设计模式的处理
    • 3. 总结:
    • 4. 最后

1. 23种设计模式之:模板方法 概述

设计模式,即 Design Patterns,是指在软件设计中,被反复使用的一种代码设计经验。使用设计模式的目的是为了可重用代码,提高代码的可扩展性和可维护性。

设计模式这个术语是上个世纪90年代由Erich Gamma、Richard Helm、Raplh Johnson和Jonhn Vlissides四个人总结提炼出来的,并且写了一本Design Patterns的书。这四人也被称为四人帮(GoF)。

为什么要使用设计模式?根本原因还是软件开发要实现可维护、可扩展,就必须尽量复用代码,并且降低代码的耦合度。设计模式主要是基于OOP编程提炼的,它基于以下几个原则:

1.2 开闭原则

由Bertrand Meyer提出的开闭原则(Open Closed Principle)是指,软件应该对扩展开放,而对修改关闭。这里的意思是在增加新功能的时候,能不改代码就尽量不要改,如果只增加代码就完成了新功能,那是最好的。

1.3 里氏替换原则

里氏替换原则是Barbara Liskov提出的,这是一种面向对象的设计原则,即如果我们调用一个父类的方法可以成功,那么替换成子类调用也应该完全可以运行。

设计模式把一些常用的设计思想提炼出一个个模式,然后给每个模式命名,这样在使用的时候更方便交流。GoF把23个常用模式分为创建型模式、结构型模式和行为型模式三类,我们后续会一一讲解。

学习设计模式,关键是学习设计思想,不能简单地生搬硬套,也不能为了使用设计模式而过度设计,要合理平衡设计的复杂度和灵活性,并意识到设计模式也并不是万能的。

什么是设计模式?

设计模式简单的来说就是:一种处理某个问题的固定的解决方案,(可以被重复使用)

常见的设计模式有23种,设计模式有被称为是 GOF设计模式 :比如:这里我们简单的列举一些设计模式:单例模式,代理模式,工厂模式,适配器模式,模板方法模式,门面设计模式,责任链设计模式,观察者模式…..。

还有一种常见的设计模式:名为 JavaEE设计模式 :比如:DAO,DTO,VO,PO,POJO ……等等,这里就就不多详细说明了。

1.4 什么是模板方法设计模式

模板方法(Template Method)是一个比较简单的模式。它的主要思想是,定义一个操作的一系列步骤,对于某些暂时确定不下来的步骤,就留给子类去实现好了,这样不同的子类就可以定义出不同的步骤。

模板方法的核心思想是:父类定义骨架,子类实现某些细节。

为了防止子类重写父类的骨架方法,可以在父类中对骨架方法使用final。对于需要子类实现的抽象方法,一般声明为protected,使得这些方法对外部客户端不可见。

从模板方法设计模式的字面意思中,我们就可以知道,其中最主要,最重要的就是 模板方法 了。对于模板方法设计模式来说,设置好合理的 模板方法是核心。将模板方法设计好了,基本上就完成了对模板方法设计模式的设计了。

一般来说模板方法是存在于 模板类当中的,而模板类通常都是 抽象类 。因为我们延迟该子类重写的方法是 抽象方法,而抽象方法只能定义在抽象类和接口当中,而接口中不能定义方法(并且接口一般是用于定义规范的)

在模板类的模板方法当中定义核心算法 骨架,具体的实现步骤可以延迟到子类的当中完成。一般核心算法是被 final 关键字修饰的(无法被覆盖,但也可以不是final的)一方面是得到了保护,不能被改变,另外一方面就是算法得到了重复使用。
在另外一方面代码也得到了复用,因为算法中某些步骤的代码是固定的,这种固定的代码不会随着子类的变化而变化,这一部分代码可以写到模板当中。

而我们延迟到子类当总中处理实现的方法,就是定义为抽象方法,这种不确定实现的方法,这个不确定怎么处理,怎么实现等等事,就交给子类去做(重写该抽象方法)。

2. 模板方法设计模式实例

下面我们将演示处理同一个事务,分别使用模板方法设计模式处理,以及不用模板方法设计模式处理,比较者两者处理的好坏。

这里我们简单的处理一个:学生和老师的一天的事务说明。

2.1 未用模板方法设计模式的处理

如下是 Student 学生类的代码设计

package com.RainbowSea.templateMethod;public class Student {    public void day() {        getUp();        brushTeeth();        eatFast();        doSome();    }    public void getUp() {        System.out.println("起床");    }    public void brushTeeth() {        System.out.println("刷牙");    }    public void eatFast() {        System.out.println("吃早饭");    }    public void doSome() {        System.out.println("学生,上课学习");    }}

如下是 Teacher老师类的代码设计

package com.RainbowSea.templateMethod;public class Teacher {    public void day() {        getUp();        brushTeeth();        eatFast();        doSome();    }    public void getUp() {        System.out.println("起床");    }    public void brushTeeth() {        System.out.println("刷牙");    }    public void eatFast() {        System.out.println("吃早饭");    }    public void doSome() {        System.out.println("老师,授课");    }}

如下是Test 运行测试的代码设计

package com.RainbowSea.templateMethod;public class Test {    public static void main(String[] args) {        Student student = new Student();        student.day();        System.out.println("*******************************");        Teacher teacher = new Teacher();        teacher.day();    }} 

上述演示的是未用模板方法设计模式的思想处理的结果:

从中我们可以看出,这两个Teacher 类和 Student 类的代码设计只有,doSome() 方法是不同的,其他的方法都是一样的处理结果,所以我们可以将重复的一样的代码整合起来,提高代码的复用性,减少代码的冗余性。如下我们就使用模板方法设计模式处理。

2.2 用了模板方法设计模式的处理

从上述未用模板方法设计模式处理,存在大量的代码冗余,代码的复用性极差。从上述的结果分析中我们可以知道:
Teacher 类和 Student 类的代码设计只有,doSome() 方法是不同的,其他的方法都是一样的处理结果。所以这里我们的模板方法的设计模式的设计:将其中的 day()方法设置为 该模板方法的核心算法骨架,而 doSome()方法这个不确定的处理方式,延迟交给继承的子类去具体实现,将其中的所有方法,定义在模板类当中,这个模板类一般都是抽象类,这里我们定义为 Person 抽象类 。 具体代码实现如下:

如下是Person模板类的设计代码

package com.RainbowSea.templateMethod;/** * Teacher 和 Student 都是Person * 1.Person 就是模板方法设计模式当中的模板类 * 2. day()方法就是模板方法设计模式当中的模板方法。 * 模板类通常是一个抽象类,模板类当中的模板方法定义核心算法,这个方法通常是final 的(但也可以不是final的) * 模板类当中的抽象方法就是不确定实现的方法,这个不确定怎么实现的事情就交给子类去做了。 * * */public abstract class Person {  // 模板类通常是抽象类        /**         * 这个方法描述学生的一天         */        // 添加了final 之后,这个方法就无法被覆盖,这样核心算法也可以得到保护。        // 模板方法:        // 模板方法定义核心的算法骨架:具体的实现步骤可以延迟到子类当中去实现。        // 核心算法一方面是得到了保护,不能被改变,另外一方面就是算法得到了重复使用。        // 另外代码也得到了复用,因为算法中某些步骤的代码是固定的,这种固定的代码不会随着子类        // 的变化而变换,这一部分代码可以写到模板当中,        public final void day() {            getUp();            brushTeeth();            eatFast();            doSome();        }        // 其中的某些步骤:不会随着子类的变化而变化,这些代码可以写到父类中,得到代码的复用。        public void getUp() {            System.out.println("起床");        }        public void brushTeeth() {            System.out.println("刷牙");        }        public void eatFast() {            System.out.println("吃早饭");        }        // 这一步是要做,但是具体这一步怎么做,子类说的算。        public abstract void doSome();  // 定义为抽象方法}

Student 类的代码设计

package com.RainbowSea.templateMethod;public class Student extends Person{    @Override    public void doSome() {        System.out.println("学生,上课学习");    }}

Teacher类的代码设计

package com.RainbowSea.templateMethod;public class Teacher extends Person{    @Override    public void doSome() {        System.out.println("老师授课、");    }}

Test运行测试

package com.RainbowSea.templateMethod;public class Test {    public static void main(String[] args) {        Person p1 = new Teacher();        p1.day();        System.out.println("*****************");        Person p2 = new Student();        p2.day();    }}

3. 总结:

  1. 设计模式:一种处理某个问题的固定的解决方案,(可以被重复使用)

  2. 模板方法(Template Method)是一个比较简单的模式。它的主要思想是,定义一个操作的一系列步骤,对于某些暂时确定不下来的步骤,就留给子类去实现好了,这样不同的子类就可以定义出不同的步骤。

  3. 模板方法的核心思想是:父类定义骨架,子类实现某些细节。

  4. 为了防止子类重写父类的骨架方法,可以在父类中对骨架方法使用final。对于需要子类实现的抽象方法,一般声明为protected,使得这些方法对外部客户端不可见。

  5. 学好设计模式,提交你代码的复用性,使你的代码更加优雅。

4. 最后

限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见!!!