C# 设计模式系列教程-模板方法模式
作者:Wang Juqiang 发布时间:2022-03-17 18:00:15
标签:C#,设计模式,模板方法模式
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();
}
}
运行结果
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- 方法的覆盖在类继承中,子类可以修改从父类继承来的方法,也就是说子类能创建一个与父类方法有不同功能的方法,但具有相同的名称、返回值类型、参数列
- 前言在java中遍历Map有不少的方法。这篇文章我们就来看一下Java读取Map的两种方法以及这两种方法的对比。一、 遍历Map方
- 前言本文主要给大家介绍了关于Spring4自定义@Value功能的相关内容,使用的Spring版本4.3.10.RELEASE,下面话不多说
- 1、什么是OpenCVSharp 为了解决在Csharp下编写OpenCV程序的问题,我做过比较深入的研究,并且实现了高效可用的
- class Dirctonary { &nbs
- application.properties有以下这几条数据方法一:@Value注解+@Component建议properties少的时候用
- 本文实例为大家分享了Java实现窗体程序显示日历的具体代码,供大家参考,具体内容如下实训要求:1.使用BorderLayout 进行总体布局
- 1.让方法返回多个参数1.1在方法体外定义变量保存结果using System; using System.Collections
- Collection遍历方式Collection集合遍历的方式有三种:迭代器foreach/增强for循环lambda表达式迭代器遍历迭代器
- 有哪些“纪律”是Java程序员所要遵守的?1. 为代码添加注释(Add comments to your code). – 每个人都知道这一
- 本文针对java * 进行知识点整理,具体内容如下一. JAVA的 * (比较官方说法) 代理模式是常用的java设计模式,他的特征是代
- 一、前言关于EasyExcel,它对poi做了进一步的封装,使得整个编写流程更加的面向对象。好处嘛,我认为流程上更加清晰即易懂、可读性更好,
- 经典的排序算法有八种,分别为:冒泡排序选择排序插入排序归并排序希尔排序快速排序堆排序基数排序其中冒泡排序、选择排序、插入排序称为三大基本排序
- 功能目标使用Treeview控件实现点左边的节点,在右边显示相关的页面知识点Treeview命名空间:System.Windows.Form
- 一:问题描述 在已经root过的android设备下,app执行一个linux命令,app需要获取su权限,在某些a
- 一、MyBatis的增删改查1.1、新增<!--int insertUser();--><insert id="
- 图片准备hole.png和slider.png为png是因为图片带有透明度。合成目标最终为前端生成两张图片:out_slider.png高度
- 在request中可以获取到来自Http请求的body数据比如获取json格式数据代码:import com.alibaba.dubbo.c
- 在java中我们常常使用加锁机制来确保线程安全,但是如果过度使用加锁,则可能导致锁顺序死锁。同样,我们使用线程池和信号量来限制对资源的使用,
- 1、抽象类1.1 什么是抽象类?1.1.1 对抽象类的理解1.1.2 关于抽象类类与类之间具有共同特征,将这些共同特征提取出来,形成的就是抽