23种设计模式之 : 模板方法设计模式
23种设计模式之 : 模板方法设计模式
每博一文案
青年,青年!无论受怎样的挫折和打击,都要咬着牙关挺住,因为你们完全有机会重建生活;只要不灰心丧气,每一次挫折就只不过是通往新境界的一块普通绊脚石,而绝不会置人于死命。
昨天很辛苦,今天很残酷,明天很美好,大部分人撑不到明天。
缘来缘去自由定数,知足常乐才是福。
就以为如此,你也应该重新走向生活!二十七年来你付出的太少,不值得接受生活如此的馈赠。
多大的痛苦也不能打乱日常的生活节拍————这就是他精神强大等我根本所在。
黄河水总有清的一天,人不能穷一辈子!
平凡的世界,质朴的人儿,渺小的心灵,然而无穷尽的对生活的热爱。
只有劳动才可能使人在生活中强大。不论什么人,最终还是要崇尚那些能用双手创造生活的劳动者。
活在这世界上,有人爱你,总不是一件坏事。
命运总是不如人愿。但往往是在无数的痛苦中,在重重的矛盾和艰辛中,才是人成熟起来。
—————— 《平凡的世界》 路遥
@
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. 总结:
-
设计模式:一种处理某个问题的固定的解决方案,(可以被重复使用)
-
模板方法(Template Method)是一个比较简单的模式。它的主要思想是,定义一个操作的一系列步骤,对于某些暂时确定不下来的步骤,就留给子类去实现好了,这样不同的子类就可以定义出不同的步骤。
-
模板方法的核心思想是:父类定义骨架,子类实现某些细节。
-
为了防止子类重写父类的骨架方法,可以在父类中对骨架方法使用
final
。对于需要子类实现的抽象方法,一般声明为protected
,使得这些方法对外部客户端不可见。 -
学好设计模式,提交你代码的复用性,使你的代码更加优雅。
4. 最后
限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见!!!