介绍

本文的目的是理解战略模式的基础知识,并试图了解何时可以使用,并有一个基本的实现,以便更好地理解。在现实世界的应用中,这是无法实施战略模式的,所采用的例子也远没有实际可行。这篇文章的想法只是为了说明战略模式的概念。

背景

应用程序开发中有很多场景,有多种方法可以进行相同的操作。我们希望我们的应用程序有可能使用所有这些执行操作的方式。一个例子可能是电子商务门户付款,我可以选择使用网上银行付款,我可以选择使用信用卡,或者我甚至可以选择贝宝进行付款。所有这些都是执行相同操作的方法。尽管每个选择都必须遵循不同的应用程序逻辑,即独立的代码。

另外一个我们可以用多种方法进行相同操作的例子是排序。我可以使用任何一种排序算法对序列进行排序。所以当我想要开发应用程序的时候,如果有任何操作,用户可以选择许多可用选项中的一种,那么也许这就是合并策略模式的合适地方。

策略模式的理念是有多种策略来做一些操作,让用户选择(或基于输入数据的某种算法)合适的策略来执行操作。GoF将策略模式定义为“定义算法家族,封装每一个算法,并使它们可以互换。策略可以让算法独立于使用它的客户端。“

让我们尝试了解这个类图的每个组件。

  • Strategy:这是所有算法的通用接口。上下文使用此接口来执行操作。
  • ConcreteStrategy:这是实现实际算法的类。
  • Context:这是执行决策的客户端应用程序,应使用哪个策略,并使用Strategy接口(指的是ConcreteStrategy对象)来执行操作。

使用代码

为了理解这些概念,让我们开发一个玩具应用程序,将音频文件从Wav转换为MP3。这里用户可以选择源.wav文件,然后选择要创建的目标MP3文件的质量。用户界面将为用户提供目标文件的三个质量值。

在我们的代码中,我们将要做的是我们将创建多个策略,每个我们将要使用的是定义输出的质量。我们正在实施所有这些独立的策略,以便转换代码不受特定于处理输出质量的代码的影响。正在进行转换的实际代码将独立于这些不同策略的实现细节,并且对于任何选定的策略或者甚至在添加新策略时都将以相同的方式工作。

注意:这不是一个真正的转换应用程序,只是一个虚拟的应用程序,但也许真正的应用程序可以在同一条线上开发。而且,应用程序和设计的选择纯粹是为了展示战略模式的行动(如果我们采取整体的观点,可能是一个糟糕的设计)。

所以让我们先写一下IWavToMp3ConvertionStrategy将由所有具体策略实现的接口。


interface IWavToMp3ConvertionStrategy
{
void Convert();
}

 

一旦我们准备好接口,我们可以编写具体的战略类。

//Strategy class for low quality conversion
class LowQualityConversionStrategy : IWavToMp3ConvertionStrategy
{
public void Convert()
{
Console.WriteLine("Low quality conversion performed");
}
} //Strategy class for average quality conversion
class AverageQualityConversionStrategy : IWavToMp3ConvertionStrategy
{
public void Convert()
{
Console.WriteLine("Average quality conversion performed");
}
} //Strategy class for high quality conversion
class HighQualityConversionStrategy : IWavToMp3ConvertionStrategy
{
public void Convert()
{
Console.WriteLine("High quality conversion performed");
}
}
我们有我们的具体类包含在所有策略中不同的逻辑。所有转换特性所共有的所有逻辑将出现在将选择实际转换策略的类中,即上图中的上下文类。因此,让我们编写Context类WavToMP3Convertor,即将使用IWavToMp3ConvertionStrategy接口来执行转换。 隐藏 复制代码
public class WavToMP3Convertor
{
AudioFile m_fileData = null;
IWavToMp3ConvertionStrategy m_Convertor = null; public WavToMP3Convertor(AudioFile fileData)
{
m_fileData = fileData;
} public void Convert(IWavToMp3ConvertionStrategy convertor)
{
m_Convertor = convertor;
m_Convertor.Convert();
}
}

这个类正在发生的是表示层正在传递实际的文件数据到这个类。那么当转换被请求时,一个具体的策略实例也将被传递给这个类,以便这个类可以使用传递的策略进行转换。

在这个代码中要注意的是,即使我们添加更多的策略,这个代码也不会受到影响。另外,如果我们要创建一个SDK / DLL,用户可以选择创建自己的策略,只需将它们传递给这个类来使用它们的自定义策略。

最后,我们将有我们的表示层,让用户决定对话策略,并将适当的策略传递给转换类。

static void Main(string[] args)
{
IWavToMp3ConvertionStrategy selectedStrategy = null; Console.WriteLine("Assuming the file for conversion has been selected already");
AudioFile file = new AudioFile { Title = "Sample File" }; // Let us try to emulate the selection of quality here
Console.WriteLine("Enter the type of output \n1. Low Quality\n2. Average Quality\n3. High Quality"); int choice = Console.Read(); // Now based on the users' choice lets go ahead and select strategy to convert the file
if (choice == '')
{
selectedStrategy = new LowQualityConversionStrategy();
}
else if (choice == '')
{
selectedStrategy = new AverageQualityConversionStrategy();
}
else if (choice == '')
{
selectedStrategy = new HighQualityConversionStrategy();
} // Now the code which is doing the conversion. this code beed
// not be changes even if we implement more strategies
if (selectedStrategy != null)
{
WavToMP3Convertor convertor = new WavToMP3Convertor(file);
convertor.Convert(selectedStrategy);
}
}

注意:本示例应用程序中的表示层正在完成策略的选择。这是创造具体战略的非常有意思的方式。在现实世界中,将根据用户在UI上的选择使用工厂或服务定位器来创建具体策略。

现在当我们运行应用程序时,我们可以看到文件转换将基于用户选择的选项而发生,并且将使用正确的策略。现在让我们尝试将我们的代码与GoF类图进行比较。

因此,我们可以看到,IWavToMp3ConvertionStrategy我们的战略是接口,WavToMP3Convertor是我们的上下文类和  LowQualityConversionStrategyAverageQualityConversionStrategyHighQualityConversionStrategy是我们的具体战略。重要的是要注意的是,Context类WavToMP3Convertor将保持不受具体策略的影响,添加/删除策略对这个类不会有任何影响。

兴趣点

在这篇文章中,我们已经看了战略模式的基础知识,以及我们如何使用这种模式将客户端代码与实际的实现分离开来。我们用一个颇为人为的例子来证明这种模式。具体策略的创建也不是使用switch语句来完成的,但是这里的目的是展示Context类如何不受策略选择的影响,从而创建具体策略的简单方法。这篇文章是从绝对的初学者的角度写的。我希望这是内容丰富的。

在C#中理解和实现策略模式的绝对入门教程的更多相关文章

  1. VMware Workstation虚拟机中的Linux通过NAT模式共享上网配置教程

    VMware Workstation虚拟机中的Linux通过NAT模式共享上网配置教程 在VMware Workstation虚拟机下面,Linux虚机要上网,一般是桥接模式,但我自己的电脑上网的环境 ...

  2. JavaScript中的设计模式:策略模式

    无论学习前端还是后端设计模式是作为一名程序员不可缺少的知识,就像下底传中对于一个边锋来说. 一.策略模式 策略模式给人的第一感觉就是在代码里面消除了很多if-else分支语句,比如一个求员工奖金的程序 ...

  3. 23中java设计模式(1)-- 策略模式

    近来不太忙,就打算抽空看下源码补充一下知识,当我看了之后我发现看源码的关键是要弄清楚类之家的关系以及为何要这样的关系,否则如果只看具体的代码那不如去学习会儿算法. 于是就打算从设计模式入手,边学习边记 ...

  4. springboot项目中使用设计模式一策略模式

    策略模式: 使用常用,支付,之前做了微信支付,支付宝支付,然后另外一个同事写了一个银联支付,那么如果代码方法一起就会导致代码不是很好操作所以,采用策略模式进行,同事只需要写一个实现类,就可以了, 在协 ...

  5. Spring中常见的设计模式——策略模式

    策略模式(Strategy Pattern) 一.策略模式的应用场景 策略模式的应用场景如下: 系统中有很多类,而他们的区别仅仅在于行为不同. 一个系统需要动态的在集中算法中选择一种 二.用策略模式实 ...

  6. ASP.NET中实现封装与策略模式

    首先把运算方法封装起来,这样在网页界面中直接就可以调用了,不过是换张脸而已! using System; using System.Collections.Generic; using System. ...

  7. 在商城系统中使用设计模式----策略模式之在spring中使用策略模式

    1.前言: 这是策略模式在spring中的使用,对策略模式不了解对同学可以移步在商城中简单对使用策略模式. 2.问题: 在策略模式中,我们创建表示各种策略的对象和一个行为,随着策略对象改变而改变的 c ...

  8. Java设计模式6:策略模式

    策略模式 策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立类中,从而使得它们可以相互替换.策略模式使得算法可以在不影响到客户端的情况下发生变化. 策略模式的结构 策略模式是对算法的包 ...

  9. 设计模式之策略模式(Strategy Pattern)

    模板方法是通过继承实现的,在父类中定义出算法的骨架,将不同点在子类中实现.而策略模式是通过接口实现的,策略中定义了完整的算法.它们有点像啊-- 策略模式的定义 策略模式(Strategy Patter ...

随机推荐

  1. ad 原件布局布线基本规则

    一.原件布局基本规则 1.按照电路模块进行布局,电路中的元件应该采用集中就近原则,同时数字电路和模拟电路分开: 2.定位孔.标准孔等周围1.27mm内不得贴元器件,安装孔周围3.5mm不得特装元件 3 ...

  2. 20165215 2017-2018-2 《Java程序设计》第4周学习总结

    20165215 2017-2018-2 <Java程序设计>第4周学习总结 教材学习内容总结 chapter5 子类与父类 子类的定义使用关键字extends 任何类都是Object类的 ...

  3. centos-ftp搭建

    参照https://blog.csdn.net/a735834365/article/details/80622105 https://blog.csdn.net/a735834365/article ...

  4. 像黑客一样使用Linux命令行(转载)

    阅读目录 前言 使用 tmux 复用控制台窗口 在命令行中快速移动光标 在命令行中快速删除文本 快速查看和搜索历史命令 快速引用和修饰历史命令 录制屏幕并转换为 gif 动画图片 总结 回到顶部 前言 ...

  5. redis的常用命令01

    启动redis的命令: redis-server redis.windows.conf把redis设置成windows下的服务的命令:输入命令后刷新会出现redis的服务:redis-server - ...

  6. STM32硬件IIC驱动设计(转)

    源: STM32硬件IIC驱动设计 参考: STM32—硬件IIC主机通信 STM32’s I2C 硬件BUG引发的血案(qzm) 解决STM32 I2C接口死锁在BUSY状态的方法讨论

  7. How to Get Text inside a Canvas using Webdriver or Protractor

    https://stackoverflow.com/questions/43609429/how-to-get-text-inside-a-canvas-using-webdriver-or-prot ...

  8. rsync 同步文件如何指定属主属组和权限

    rsync daemon 同步数据时,若想同时指定权限和属主属组,可以做如下配置: [test1] uid = admin gid = admin incoming chmod = Dug=rwx,D ...

  9. 9i时候的块

    Header (Common and Variable) The header contains general block information, such as the block addres ...

  10. mysql备份与还原-mysqldump备份、mysql与source还原

    以下都以在linux操作系统上的mysql为例 mysqldump备份 mysqldump实际就是将数据库中的数据转化为建库.建表和插入记录的sql语句 1.备份一个数据库 [或其中几个表],不指定表 ...