文档章节

设计模式系列之Template Method(模板方法模式)

卧雪Sirk
 卧雪Sirk
发布于 2016/03/19 08:54
字数 1654
阅读 5
收藏 0
点赞 1
评论 0

     在面向对象设计中,无非就是封装,继承之类的运用,而设计出可扩展性好,代码冗余少,可重用性高的程序也是衡量面向对象开发的一个标准。面向对象使用相当灵活,虽然核心特征只有封装,继承,多态,但是通过对它们的灵活配合和使用变化出了各种设计模式。可以说,设计模式是对面向对象的一些经验总结,今天将看到其中的一个,Template Method(模板方法模式)。

 

Template Method(模板方法模式) 

 

    定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Te m p l a t e M e t h o d使得子类

可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 (摘自:《设计模式:可复用面向对象软件的基础》)

 

    那么如何来理解上述的定义呢?可以这样想,模板方法,说到底也是一个方法,而它的作用正如其名--模板。在这个模板里面,定义了一系列连续的动作。这样,当调用这个模板方法后,其内部的方法将被按照顺序调用。但是,仅此而已的话,只是对一系列方法进行了封装,根本没有体现面向对象,其关键在定义的后半句,将一些步骤延迟到子类中。模板方法为了减少代码冗余,将子类中相同的操作提取出来,放到抽象父类中,这些方法我们叫做具体方法(Concrete Method),而如果是不同的操作的话,就在抽象类中定义它们的抽象方法(Abstract Method),把具体的实现延迟到子类中去。除此之外,在抽象父类中还有一类方法,这类方法在需要的时候,可以在子类中实现它们,与抽象方法不同的是在子类中比较自由,没有强制性要求实现,此类方法叫做钩子方法(HookMethod),为了区别抽象方法,在定义时一般以Do开头,例如DoCloseDocument();上述三类方法都将被放到模板方法中(Template Method)。这样,在客户端中,我们调用模板方法,模板方法调用将是不变的,因为在模板方法中的算法结构是固定不变的,但是可以通过实现不同的子类方法,重定义算法的某些特定步骤。

 
     上述描述的有点多,看着晕了,还是以一个简单的例子再来理解下:

 

如何把大象放进冰箱 

 

      记得这是赵本山很久以前的一个小品《钟点工》里的一个例子,虽然当年这个节目的时候,我年纪还很小,但是竟然还印象深刻。这里,就用这个例子来演示模板方法模式。


一、分析此过程

 通过此例子,我们知道,把大象放进冰箱,需要三步(不考虑冰箱中是否有长颈鹿或者冰箱已经满了,我们忽略这些):

 

1.打开冰箱

2.把大象放进去

3.关上冰箱

 

二、抽象出更抽象的过程

 

    可以放大象,当然可以放其它东西,比如放小鸡,放长颈鹿等等,所有的这些东西我们就叫东西,这话听怎么这么奇怪,那就书面化点,所有的这些东西我们叫做对象。

这样,抽象出的一个基类可以叫做:Abstract class PutSomethingIntoFridge{}

 然后,在基类中我们把东西放进冰箱的一系列算法步骤写入Put()的模板方法中。

然后....此处省略100个字,具体看下文代码 

 

 三、继承父类,实现各种东西放进冰箱

 


设计完成后,整个结构如下图所示:

 

示例代码:

PutSomethingIntoFridge.cs

 

using   System;

 namespace   PatternDemo
{
    
 abstract     class   PutSomethingIntoFridge
    {
        
 //  模板方法  
           public     void   Put()
        {
            
 //  具体方法  
             OpenFridge();
            
 //  Hook方法,扩大冰箱容量  
             DoEnlargeCapacity();
            
 //  抽象方法  
             PutInto();
            
 //  具体方法  
             CloseFridge();
        
        }

        
 //  具体方法,无需在子类中重新实现  
           protected      void   OpenFridge()
        {
            Console.WriteLine(
 "  打开冰箱  "  );
        
        }

        
 //  具体方法,无需在子类中重新实现  
           protected     void   CloseFridge()
        {

            Console.WriteLine(
 "  关上冰箱  "  );
        
        }

        
 //  抽象方法,在子类中强制实现  
           abstract     protected     void   PutInto();

        
 //  Hook方法,扩大冰箱容量,此方法在子类中可选择实现。换句话说,只有在必要的时候才重写实现它  
          virtual     protected     void   DoEnlargeCapacity(){}

    }
}

 

 

 PutChickenIntoFridge.cs

using System;  
 namespace   PatternDemo
{
    
 class   PutChickenIntoFridge : PutSomethingIntoFridge
    {
        
 //  普通冰箱能放下一只鸡,当然是在冰箱没有满的情况下,所以只要实现具体放的东西方法就行  
           protected     override     void   PutInto()
        {
            Console.WriteLine(
 "  把鸡放进冰箱  "  );
        }
    }
}



PutElephantIntoFridge

using    System;

  namespace    PatternDemo
{
    
  class    PutElephantIntoFridge : PutSomethingIntoFridge
    {
        
  //   由于大象太大,普通冰箱无法放进去,需要扩大冰箱容量,所以实现DoEnlargeCapacity方法  
             protected       override       void    DoEnlargeCapacity()
        {
            Console.WriteLine(
  "   扩大冰箱容量10000倍   "   );
        }

        
  protected       override       void    PutInto()
        {
            Console.WriteLine(
  "   把大象放进冰箱   "   );
        }
    }
 


Client

namespace    PatternDemo
{
    
  class    Client
    {
        
  static       void    Main(   string   [] args)
        {
            PutSomethingIntoFridge putchicken 
  =       new    PutChickenIntoFridge();
            putchicken.Put();

            PutSomethingIntoFridge putelephant 
  =       new    PutElephantIntoFridge();
            putelephant.Put();
            
        }
    }
 



对与Template Method(模板方法)的一些总结

 


 模板方法是一种代码复用的基本技术,它们在类库中尤为重要,它们提取了类库中的公共行为。

 模板方法的适用情况:

• 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。

• 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。首先识别

现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的

操作的模板方法来替换这些不同的代码。

• 控制子类扩展。模板方法只在特定点调用“ h o o k”操作(例如这里举例的当冰箱装不下大象这样的特殊情况时),这样就只允

许在这些点进行扩展。

 

 需要注意的地方:

1.为了保证模板方法中调用的各种原语操作(抽象方法,具体方法,Hook方法)只能被模板方法调用,访问权限应为protected。

2.尽量减少原语操作。以防客户端代码冗长。

3.避免乱用模板方法,导致子类泛滥,应根据具体情况适时的使用。

 

 参考资料

《设计模式:可复用面向对象软件的基础》


 

© 著作权归作者所有

共有 人打赏支持
卧雪Sirk

卧雪Sirk

粉丝 0
博文 60
码字总数 23226
作品 4
杭州
技术主管
代理模式(Proxy Pattern):动态代理 - 最易懂的设计模式解析

前言 今天我来全面总结开发中最常用的设计模式 - 代理模式中的动态代理模式 其他设计模式介绍 1分钟全面了解“设计模式” 单例模式(Singleton) - 最易懂的设计模式解析 简单工厂模式(Sim...

Carson_Ho ⋅ 04/09 ⋅ 0

Template Method 模板设计模式

什么是模板设计模式 对于不了解的模板设计模式的来说,可以认为如同古代的造纸术一样,纸所以成型,取决于用了模板的形状,形状又由镂空的木板组成,而你想要造什么纸,又取决于你使用什么材料. 上...

---dgw博客 ⋅ 04/28 ⋅ 0

【聚能聊话题】聊聊设计模式,封装算法——模板方法模式

前面我们聊了: 什么是设计模式?你知道多少? 你必须知道的六大设计原则 第一个设计模式,我是皇帝我独苗,单例模式 第二个设计模式,工厂方法模式 第三个设计模式,抽象工厂模式 这个真的很...

微wx笑 ⋅ 05/29 ⋅ 0

Factory Method (工厂模式)

什么是工厂设计模式 根据名字即可了解,工厂肯定是用来生产产品的,在我们的程序开发中,需要用到不同的类,对于熟悉SSH、SSM开发的可以知道,在初期学习的时候,总是有一个框架提供好的的f...

---dgw博客 ⋅ 05/07 ⋅ 0

[设计模式]简单工厂模式

简介 简单工厂模式 (Simple Factory) 又叫静态工厂方法(Static Factory Method)模式。 简单工厂模式通常是定义一个工厂类,这个类可以根据不同变量返回不同类的产品实例。 简单工厂模式是一...

静默虚空 ⋅ 2015/06/03 ⋅ 0

JavaScript 中常见设计模式整理

开发中,我们或多或少地接触了设计模式,但是很多时候不知道自己使用了哪种设计模式或者说该使用何种设计模式。本文意在梳理常见设计模式的特点,从而对它们有比较清晰的认知。 JavaScript 中...

牧云云 ⋅ 05/18 ⋅ 0

设计模式Java Design Pattern-工厂方法模式FactoryMethod

我的博客 一、 设计模式的分类 大体可以分为三类: 创建型模式(5个) 单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式 结构性模式(7个) 适配器模式、装饰器模式、代理模式、...

勇敢写信 ⋅ 03/22 ⋅ 0

你需要了解的23种JavaScript设计模式

为什么要学习设计模式? 在许多访谈中,你可能会遇到很多面向对象编程中的接口,抽象类,代理和以及其他与设计模式相关的问题。 一旦了解了设计模式,它会让你轻松应对任何访谈,并可以在你的...

java高级架构牛人 ⋅ 06/02 ⋅ 0

java基础---深入解析spring中用到的九种设计模式

转载请注明出处,文章首发于:http://itxxz.com/a/javashili/tuozhan/2014/0601/7.html 设计模式作为工作学习中的枕边书,却时常处于勤说不用的尴尬境地,也不是我们时常忘记,只是一直没有记...

u010775025 ⋅ 04/25 ⋅ 0

设计模式分类与原则

创建型模式 这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。 工厂模式(...

晨猫 ⋅ 03/12 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

使用 vue-cli 搭建项目

vue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目,GitHub地址是:https://github.com/vuejs/vue-cli 一、 安装 node.js 首先需要安装node环境,可以直接到中...

初学者的优化 ⋅ 24分钟前 ⋅ 0

设计模式 之 享元模式

设计模式 之 享元模式 定义 使用共享技术来有效地支持大量细粒度对象的复用 关键点:防止类多次创建,造成内存溢出; 使用享元模式来将内部状态与外部状态进行分离,在循环创建对象的环境下,...

GMarshal ⋅ 39分钟前 ⋅ 0

SpringBoot集成Druid的最简单的小示例

参考网页 https://blog.csdn.net/king_is_everyone/article/details/53098350 建立maven工程 Pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM......

karma123 ⋅ 今天 ⋅ 0

Java虚拟机基本结构的简单记忆

Java堆:一般是放置实例化的对象的地方,堆分新生代和老年代空间,不断未被回收的对象越老,被放入老年代空间。分配最大堆空间:-Xmx 分配初始堆空间:-Xms,分配新生代空间:-Xmn,新生代的大小一...

算法之名 ⋅ 今天 ⋅ 0

OSChina 周日乱弹 —— 这么好的姑娘都不要了啊

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @TigaPile :分享曾惜的单曲《讲真的》 《讲真的》- 曾惜 手机党少年们想听歌,请使劲儿戳(这里) @首席搬砖工程师 :怎样约女孩子出来吃饭,...

小小编辑 ⋅ 今天 ⋅ 8

Jenkins实践3 之脚本

#!/bin/sh# export PROJ_PATH=项目路径# export TOMCAT_PATH=tomcat路径killTomcat(){pid=`ps -ef | grep tomcat | grep java|awk '{print $2}'`echo "tom...

晨猫 ⋅ 今天 ⋅ 0

Spring Bean的生命周期

前言 Spring Bean 的生命周期在整个 Spring 中占有很重要的位置,掌握这些可以加深对 Spring 的理解。 首先看下生命周期图: 再谈生命周期之前有一点需要先明确: Spring 只帮我们管理单例模...

素雷 ⋅ 今天 ⋅ 0

zblog2.3版本的asp系统是否可以超越卢松松博客的流量[图]

最近访问zblog官网,发现zlbog-asp2.3版本已经进入测试阶段了,虽然正式版还没有发布,想必也不久了。那么作为aps纵横江湖十多年的今天,blog2.2版本应该已经成熟了,为什么还要发布这个2.3...

原创小博客 ⋅ 今天 ⋅ 0

聊聊spring cloud的HystrixCircuitBreakerConfiguration

序 本文主要研究一下spring cloud的HystrixCircuitBreakerConfiguration HystrixCircuitBreakerConfiguration spring-cloud-netflix-core-2.0.0.RELEASE-sources.jar!/org/springframework/......

go4it ⋅ 今天 ⋅ 0

二分查找

二分查找,也称折半查找、二分搜索,是一种在有序数组中查找某一特定元素的搜索算法。搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束;如果某一特定元素大于...

人觉非常君 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部