模板方法模式深度解析(一)

1. 概述

  定义一个操作中的算法的骨架,而将步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义算法的某些特定步骤。

2. 模式中的角色

  2.1 抽象类(AbstractClass):实现了模板方法,定义了算法的骨架。

  2.2 具体类(ConcreteClass):实现抽象类中的抽象方法,已完成完整的算法。

3. 模式解读

  3.1 模板方法类图

  

  3.2 模板方法模式代码实现

    /// <summary>
    /// 抽象类
    /// </summary>
    public abstract class AbstractClass
    {
        // 一些抽象行为,放到子类去实现
        public abstract void PrimitiveOperation1();
        public abstract void PrimitiveOperation2();

        /// <summary>
        /// 模板方法,给出了逻辑的骨架,而逻辑的组成是一些相应的抽象操作,它们推迟到子类去实现。
        /// </summary>
        public void TemplateMethod()
        {
            PrimitiveOperation1();
            PrimitiveOperation2();
            Console.WriteLine("Done the method.");
        }
    }

    /// <summary>
    /// 具体类,实现了抽象类中的特定步骤
    /// </summary>
    public class ConcreteClassA : AbstractClass
    {
        /// <summary>
        /// 与ConcreteClassB中的实现逻辑不同
        /// </summary>
        public override void PrimitiveOperation1()
        {
            Console.WriteLine("Implement operation 1 in Concreate class A.");
        }

        /// <summary>
        /// 与ConcreteClassB中的实现逻辑不同
        /// </summary>
        public override void PrimitiveOperation2()
        {
            Console.WriteLine("Implement operation 2 in Concreate class A.");
        }
    }

    /// <summary>
    /// 具体类,实现了抽象类中的特定步骤
    /// </summary>
    public class ConcreteClassB : AbstractClass
    {
        /// <summary>
        /// 与ConcreteClassA中的实现逻辑不同
        /// </summary>
        public override void PrimitiveOperation1()
        {
            Console.WriteLine("Implement operation 1 in Concreate class B.");
        }

        /// <summary>
        /// 与ConcreteClassA中的实现逻辑不同
        /// </summary>
        public override void PrimitiveOperation2()
        {
            Console.WriteLine("Implement operation 2 in Concreate class B.");
        }
    }

  3.3 客户端代码

    class Program
    {
        static void Main(string[] args)
        {
            // 声明抽象类
            AbstractClass c;

            // 用ConcreteClassA实例化c
            c = new ConcreteClassA();
            c.TemplateMethod();

            // 用ConcreteClassB实例化c
            c = new ConcreteClassB();
            c.TemplateMethod();

            Console.Read();
        }
    }

  运行结果

  

5. 模式总结

  5.1 优点

    5.1.1 模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。

    5.1.2 子类实现算法的某些细节,有助于算法的扩展。

    5.1.3 通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。

  5.2 缺点

    5.2.1 每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。

  5.3 适用场景

    5.1 在某些类的算法中,用了相同的方法,造成代码的重复。

    5.2 控制子类扩展,子类必须遵守算法规则。

6. 模式举例: 用冒泡算法非别对整型数组、浮点数数组、日期数组实现排序。

  6.1 实现类图

  

  6.2 实现代码

  

    /// <summary>
    /// 抽象类,定义冒泡排序的骨架
    /// </summary>
    public abstract class BubbleSorter
    {
        private int operations = 0;
        protected int length = 0;

        /// <summary>
        /// 冒泡排序算法
        /// </summary>
        /// <returns></returns>
        protected int DoSort()
        {
            operations = 0;
            if (length <= 1)
            {
                return operations;
            }

            for (int nextToLast = length - 2; nextToLast >= 0; nextToLast--)
            {
                for (int index = 0; index <= nextToLast; index++)
                {
                    if (OutOfOrder(index))
                    {
                        Swap(index);
                    }

                    operations++;
                }
            }

            return operations;
        }

        /// <summary>
        /// 留给子类实现的交换位置方法
        /// </summary>
        /// <param name="index"></param>
        protected abstract void Swap(int index);
        /// <summary>
        /// 留给子类实现的比较方法
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        protected abstract bool OutOfOrder(int index);
    }

    /// <summary>
    /// 整型类型的冒泡算法实现
    /// </summary>
    public class IntBubbleSorter:BubbleSorter
    {
        private int[] array = null;

        /// <summary>
        /// 用冒泡算法排序
        /// </summary>
        /// <param name="theArray"></param>
        /// <returns></returns>
        public int Sort(int[] theArray)
        {
            array = theArray;
            length = array.Length;
            // 调用冒泡算法
            return DoSort();
        }

        /// <summary>
        /// 实现冒泡算法中的交换操作
        /// </summary>
        /// <param name="index"></param>
        protected override void Swap(int index)
        {
            int temp = array[index];
            array[index] = array[index + 1];
            array[index + 1] = temp;
        }

        /// <summary>
        /// 实现冒泡算法中的比较操作
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        protected override bool OutOfOrder(int index)
        {
            return (array[index] > array[index + 1]);
        }
    }

    /// <summary>
    /// 浮点数类型的冒泡算法
    /// </summary>
    public class FloatBubbleSorter:BubbleSorter
    {
        private float[] array = null;

        /// <summary>
        /// 用冒泡算法排序
        /// </summary>
        /// <param name="theArray"></param>
        /// <returns></returns>
        public int Sort(float[] theArray)
        {
            array = theArray;
            length = array.Length;
            // 调用冒泡算法
            return DoSort();
        }

        /// <summary>
        /// 实现冒泡算法中的交换操作
        /// </summary>
        /// <param name="index"></param>
        protected override void Swap(int index)
        {
            float temp = array[index];
            array[index] = array[index + 1];
            array[index + 1] = temp;
        }

        /// <summary>
        /// 实现冒泡算法中的比较操作
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        protected override bool OutOfOrder(int index)
        {
            return (array[index] > array[index + 1]);
        }
    }

  6.3 客户端调用

    class Program
    {
        static void Main(string[] args)
        {

            // 对整型数组排序
            int[] intArray = new int[]{5, 3, 12, 8, 10};
            BubbleSorter.IntBubbleSorter sorter = new BubbleSorter.IntBubbleSorter();
            sorter.Sort(intArray);
            foreach (int item in intArray)
            {
                Console.Write(item+" ");
            }

            Console.WriteLine("");

            // 对浮点数排序
            float[] floatArray = new float[] { 5.0f, 3.0f, 12.0f, 8.0f, 10.0f };
            BubbleSorter.FloatBubbleSorter floatSorter = new BubbleSorter.FloatBubbleSorter();
            floatSorter.Sort(floatArray);
            foreach (float item in floatArray)
            {
                Console.Write(item + " ");
            }

            Console.Read();
        }
    }
时间: 2024-10-25 20:39:58

模板方法模式深度解析(一)的相关文章

设计模式之模板方法模式实战解析

本文微信公众号「AndroidTraveler」首发. 背景 最近在看<设计模式之禅>,为了能够更加深入的理解设计模式,达到学以致用. 这边记录一下自己的一些感受和看法,并结合具体代码实战来进行说明. 模板方法模式 但凡和设计模式挂上钩,我们总是会觉得「高不可攀」. 然而实际上,设计模式是基于大量实际代码的经验总结,它来自于实际的代码. 与其说「高不可攀」,其实它反而是比较「接地气」. 而模板方法模式相信你看完本篇文章之后,会发现,原来这就是模板方法模式,然后就去看你之前的代码了. 小例子初识

解释器模式 深度解析(2)

上一章已经初步介绍了解释器模式 这一章将 通过模式的 适用环境 ,解决方案,解决问题 ,模式应用来进一步介绍解释其模式 模式定义: 解释器模式(Interpreter Pattern) :定义语言的文法,并且建立一个解释器来解释该语言中的句子,这里的"语言"意思是使用规定格式和语法的代码,它是一种类行为型模式. 适用环境: 在以下情况下可以使用解释器模式: 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树. 一些重复出现的问题可以用一种简单的语言来进行表达. 文法较为简单. 效

【大话设计模式】—— 模板方法模式

一.概念 上一篇文章刚刚讲了[大话设计模式]-- 原型模式,原型模式主要是通过Clone()方法,创建新的对象,免去了初始化的过程.模板方法模式也特别会"偷工减料",把不变的行为搬移到超类,去除子类中的重复代码,将代码的复用优势展现的淋漓尽致.它为我们提供了特定的结构和样式,我们只需关心填充数据内容就好,省心啊- 下面让我们来看一下它的准确定义: 模板方法(TemplateMethod)模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构

菜鸟译文(二)——使用Java泛型构造模板方法模式

如果你发现你有很多重复的代码,你可能会考虑用模板方法消除容易出错的重复代码.这里有一个例子:下面的两个类,完成了几乎相同的功能: 实例化并初始化一个Reader来读取CSV文件: 读取每一行并解析: 把每一行的字符填充到Product或Customer对象: 将每一个对象添加到Set里: 返回Set. 正如你看到的,只有有注释的地方是不一样的.其他所有步骤都是相同的. ProductCsvReader.java public class ProductCsvReader {       Set<

Kafka深度解析

Kafka深度解析 原创文章,转载请务必将下面这段话置于文章开头处(保留超链接).本文转发自Jason's Blog,原文链接 http://www.jasongj.com/2015/01/02/Kafka深度解析 背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能 高吞吐率.即使在非常廉价的商用机器上也能做到单机支持每秒100K条消息的传输 支持Kafk

Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN

http://m.blog.csdn.net/blog/wu010555688/24487301 本文整理了网上几位大牛的博客,详细地讲解了CNN的基础结构与核心思想,欢迎交流. [1]Deep learning简介 [2]Deep Learning训练过程 [3]Deep Learning模型之:CNN卷积神经网络推导和实现 [4]Deep Learning模型之:CNN的反向求导及练习 [5]Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN [6]Deep Learn

SpringMVC 源代码深度解析&lt;context:component-scan&gt;(扫描和注册的注解Bean)

我们在SpringMVC开发项目中,有的用注解和XML配置Bean,这两种都各有自己的优势,数据源配置比较经常用XML配置,控制层依赖的service比较经常用注解等(在部署时比较不会改变的),我们经常比较常用的注解有@Component是通用标注,@Controller标注web控制器,@Service标注Servicec层的服务,@Respository标注DAO层的数据访问.SpringMVC启动时怎么被自动扫描然后解析并注册到Bean工厂中去(放到DefaultListableBeanF

设计模式之模板方法模式(Template Method)摘录

23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象.创建型模式有两个不断出现的主旋律.第一,它们都将关于该系统使用哪些具体的类的信息封装起来.第二,它们隐藏了这些类的实例是如何被创建和放在一起的.整个系统关于这些对象所知道的是由抽象类所定义的接口.因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以

Android Service 深度解析(1)

Android Service 深度解析(1) 这段时间我重新对Android基础进行了学习,还是先从官方文档开始,做了关于Service的文档翻译,熟悉了关于Service的知识点.但是在用的时候还是有很多需要注意的地方,需要把这些知识点联系起来,因此有了这篇文章.我将主要从以下几个方面对Service类进行深度解析: 1. Service的生命周期(看起来简单,实际上很复杂的): 2. 绑定运行Service(Bound Service)的多种形式实现及其使用: 主要包括本地Service继