介绍

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

背景

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

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

策略模式的理念是有多种策略来做一些操作,让用户选择(或基于输入数据的某种算法)合适的策略来执行操作。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. JS实现document.ready

    通常我们想要在页面内容加载完成后运行 JS 时,都会使用 window.onload 来处理,比如: window.onload = function(){ alert('Hello World!') ...

  2. Symfony2 学习笔记之服务容器

    现在的PHP应用程序都是面向对象开发,所以主要是由对象构成.有的对象可以方便的分发邮件信息而有的可能帮你把信息写入到数据库中.在你的应用程序中,你可能创建一个对象用于管理你的产品库存,或者另外一个对象 ...

  3. 一位前辈的博客,收获颇丰,包括Android、Java、linux、前端、大数据、网络安全等等

    https://www.cnblogs.com/lr393993507/   魔流剑

  4. 报文、http、https的理解

    一.何为报文?     报文是网络中交换与传输的数据单位,即站点一次性要发送的数据块.报文包含了将要发送的完整的数据信息,其长短不一致,长度不限且可变. 二.报文的作用     报文多是多个系统之间需 ...

  5. Linux网络管理(一):网卡驱动与Linux内核

    下图简单描述了网卡驱动与Linux内核之间的联系: 关于上图的一些说明: 系统初始化: 1. 协议模块调用 dev_add_pack() 来注册协议处理函数到链表 &ptype_base: 2 ...

  6. Docker学习笔记之docker volume 容器卷的那些事(二)

    预览目录 更改目录拥有者 Data Container 切换用户 参考文章 0x00 概述 如果你读了docker volume 容器卷的那些事(一),我想应该不会遇到下面这些问题的,毕竟是具有指导意 ...

  7. PyCharm‘s Project Deployment

    当在本地写完项目,部署到服务器上调试的时候,难免会碰到代码的修修改改,但由于项目在服务器上,修改起来相对麻烦.各路大神或许有自己的方法去解决.这篇博客演示利用PyCharm的Deployment功能, ...

  8. v-on事件绑定指令

    v-on:事件绑定 v-on简写:@ 绑定click事件时: 代码: <script> window.onload= () =>{ let vm=new Vue({ el:'#two ...

  9. Java常用API基础

    1:打开帮助文档2:点击显示,找到索引,看到输入框3:你要学习什么内容,你就在框框里面输入什么内容 举例:Random4:看包 java.lang包下的类在使用的时候是不需要导包的5:看类的描述 Ra ...

  10. java基础篇之理解synchronized的用法

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this ...