23种设计模式之 : 模板方法设计模式 Posted 2023-03-30 ChinaRainbowSea
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
public abstract class Person
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. 最后
限于自身水平,其中存在的错误,希望大家给予指教,韩信点兵——多多益善,谢谢大家,后会有期,江湖再见!!!
设计模式之模板方法
设计模式之模板方法
Aug 16, 2015
模板方法(TemplateMethod)定义了一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 模板方法是一种代码复用的基本技术,在类库中尤为重要,因为他们提取了类库中的公共行为。模板方法导致一种反向的控制结构,这种结构就是传说中的“好莱坞法则”,即“别找我们,我们找你”,这指的是父类调用一个类的操作,而不是相反。具体体现是面向对象编程编程语言里的抽象类(以及其中的抽象方法),以及继承该抽象类(和抽象方法)的子类。
正文
举个例子,泡茶和泡咖啡有同样的步骤,比如烧开水(boilWater)、冲泡(brew)、倒在杯子里(pourOnCup),加小料(addCondiments)等等。但每种饮料冲泡的方法以及所加的小料不一样,所以我们可以利用模板方法实现这个主要步骤。
首先先来定义抽象步骤:
var CaffeineBeverage = function () {
};
CaffeineBeverage.prototype.prepareRecipe = function () {
this.boilWater();
this.brew();
this.pourOnCup();
if (this.customerWantsCondiments()) {
// 如果可以想加小料,就加上
this.addCondiments();
}
};
CaffeineBeverage.prototype.boilWater = function () {
console.log("将水烧开!");
};
CaffeineBeverage.prototype.pourOnCup = function () {
console.log("将饮料到再杯子里!");
};
CaffeineBeverage.prototype.brew = function () {
throw new Error("该方法必须重写!");
};
CaffeineBeverage.prototype.addCondiments = function () {
throw new Error("该方法必须重写!");
};
// 默认加上小料
CaffeineBeverage.prototype.customerWantsCondiments = function () {
return true;
};
该函数在原型上扩展了所有的基础步骤,以及主要步骤,冲泡和加小料步骤没有实现,供具体饮料所对应的函数来实现,另外是否加小料(customerWantsCondiments )默认返回 true,子函数重写的时候可以重写该值。
下面两个函数分别是冲咖啡和冲茶所对应的函数:
// 冲咖啡
var Coffee = function () {
CaffeineBeverage.apply(this);
};
Coffee.prototype = new CaffeineBeverage();
Coffee.prototype.brew = function () {
console.log("从咖啡机想咖啡倒进去!");
};
Coffee.prototype.addCondiments = function () {
console.log("添加糖和牛奶");
};
Coffee.prototype.customerWantsCondiments = function () {
return confirm("你想添加糖和牛奶吗?");
};
//冲茶叶
var Tea = function () {
CaffeineBeverage.apply(this);
};
Tea.prototype = new CaffeineBeverage();
Tea.prototype.brew = function () {
console.log("泡茶叶!");
};
Tea.prototype.addCondiments = function () {
console.log("添加柠檬!");
};
Tea.prototype.customerWantsCondiments = function () {
return confirm("你想添加柠檬嘛?");
};
另外使用 confirm,可以让用户自己选择加不加小料,很不错,不是嘛?
总结
模板方法应用于下列情况:
一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现
各子类中公共的行为应被提取出来并集中到一个公共父类中的避免代码重复,不同之处分离为新的操作,最后,用一个钓鱼这些新操作的模板方法来替换这些不同的代码
控制子类扩展,模板方法只在特定点调用“hook”操作,这样就允许在这些点进行扩展
和策略模式不同,模板方法使用继承来改变算法的一部分,而策略模式使用委托来改变整个算法。
同步与推荐
深入理解 JavaScript 系列文章,包括了原创,翻译,转载等各类型的文章,如果对你有用,请推荐支持一把,给大叔写作的动力。
以上是关于23种设计模式之 : 模板方法设计模式的主要内容,如果未能解决你的问题,请参考以下文章
GoF 23 种设计模式之委派模式和模板方法模式
GoF 23 种设计模式之委派模式和模板方法模式
23种设计模式之 : 模板方法设计模式
GoF23种设计模式之行为型模式之模板方法
23种设计模式之模板方法(Template Method)
GOF23设计模式之模板方法模式(template method)