介绍

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

背景

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

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

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

    安全测试===sqlmap(壹)转载   六.优化 这些参数可以优化Sqlmap的性能. 1.一键优化 参数:-o 添加此参数相当于同时添加下列三个优化参数: --keep-alive --null- ...

  2. Java注解的原理

    自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecated这样的注解.这篇文章中,我将向大家讲述 ...

  3. Linux服务器---流量监控bandwidthd

    Bandwidthd Bandwidthd是一款免费的流量监控软件,它可以用图标的方式展现出网络流量行为,并且可区分出ftp.tcp等各种协议的流量. 1.安装一些依赖软件 [root@localho ...

  4. 【JavaScript 6连载】三、构造函数

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  5. nginx FastCGI错误Primary script unknown解决办法

    在centos上成功编译安装nginx 1.4.php 5.4并成功启动nginx和php-fpm后,访问php提示"File not found.",同时在错误日志中看到: 复制 ...

  6. [转载]Java中的String,StringBuilder,StringBuffer三者的区别

    最近在学习Java的时候,遇到了这样一个问题,就是String,StringBuilder以及StringBuffer这三个类之间有什么区别呢,自己从网上搜索了一些资料,有所了解了之后在这里整理一下, ...

  7. Django框架----视图(views)

    Django的Views(视图) 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误 ...

  8. Redis Windows 安装

    摘自:https://www.cnblogs.com/M-LittleBird/p/5902850.html 一.下载windows版本的Redis 去官网找了很久,发现原来在官网上可以下载的wind ...

  9. Java常考面试题(一)

    https://blog.csdn.net/linzhiqiang0316/article/details/80473906

  10. JS笔记—03(DOM编程)

    1. 动态体现:HTML代码加载到浏览器,代码运行后改变文档(DOM树)增删改查节点.例如:ajax(不是新技术,是几个技术的合体js+http后台操作)就是这样的原理 2.js对象(浏览器对象.脚本 ...