介绍

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

背景

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

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

策略模式的理念是有多种策略来做一些操作,让用户选择(或基于输入数据的某种算法)合适的策略来执行操作。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. 20165305 苏振龙《Java程序设计》第四周课上测试补做

    第一次测试 第二次测试 第三次测试 上传代码 第四次测试 总结 之前我一直在git bash进行程序设计,但是对于我来说操作起来有点困难,所以我改用了虚拟机,之后之前一直困扰我的问题在虚拟机下就没有了 ...

  2. js里用append()和appendChild有什么区别?

    parentNode.append()是还在试用期的方法,有兼容问题.是在parendNode节点中最后一个子节点后插入新Node或者DOMString(字符串,插入后为Text节点). 与paren ...

  3. Redis性能监控

    参考地址: redis教程:http://www.runoob.com/redis/redis-tutorial.html redis百度百科:https://baike.baidu.com/item ...

  4. react+redux+react-router+node.js 开发实时聊天App 学习记录

    一.课程导学 1.React 主要解决的是UI层的问题,应用的状态需要借助Redux等状态管理. 2.前端React  +  antd-mobile UI组件库 + Redux 状态管理库 + Rea ...

  5. canvas绘图,html5 k线图,股票行情图

    canvas绘图,html5 k线图,股票行情图 canvas跟其他标签一样,也可以通过css来定义样式.但这里需要注意的是:canvas的默认宽高为300px * 150px,在css中为canva ...

  6. [转载]图解程序员必须掌握的Java常用8大排序算法

    这篇文章主要介绍了Java如何实现八个常用的排序算法:插入排序.冒泡排序.选择排序.希尔排序 .快速排序.归并排序.堆排序和LST基数排序,分享给大家一起学习. 分类1)插入排序(直接插入排序.希尔排 ...

  7. linux利用scp远程上传下载文件/文件夹

    scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度. 当你服务 ...

  8. Eloquent JavaScript #01# values

    When action grows unprofitable, gather information; when information grows unprofitable, sleep.      ...

  9. 问题:grid卸载后重新安装时ASM磁盘识别不到了

    现象,磁盘路径是对的,但是识别不出来asmdisk2 系统显示磁盘也存在 识别不到的原因是:安装了一次磁盘已经有asm信息写入,需要擦除才能重新被识别到,命令如下 [root@swnode1 dev] ...

  10. LVS群集配置

    第一步:网络环境配置内网网段:10.0.0.0/24DR:10.0.0.254rs1:10.0.0.1rs2:10.0.0.2nfs:10.0.0.3 第二步:nfs和web服务搭建 nfs服务器:安 ...