您的位置:首页 > 其它

在C#中理解和实现策略模式的绝对入门教程

2017-12-20 23:50 441 查看


介绍

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


背景

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

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

策略模式的理念是有多种策略来做一些操作,让用户选择(或基于输入数据的某种算法)合适的策略来执行操作。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 == '1')
{
selectedStrategy = new LowQualityConversionStrategy();
}
else if (choice == '2')
{
selectedStrategy = new AverageQualityConversionStrategy();
}
else if (choice == '3')
{
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 
是我们的上下文类和  
LowQualityConversionStrategy
,  
AverageQualityConversionStrategy 
和  
HighQualityConversionStrategy 
是我们的具体战略。重要的是要注意的是,Context类
WavToMP3Convertor 
将保持不受具体策略的影响,添加/删除策略对这个类不会有任何影响。 


兴趣点

在这篇文章中,我们已经看了战略模式的基础知识,以及我们如何使用这种模式将客户端代码与实际的实现分离开来。我们用一个颇为人为的例子来证明这种模式。具体策略的创建也不是使用switch语句来完成的,但是这里的目的是展示Context类如何不受策略选择的影响,从而创建具体策略的简单方法。这篇文章是从绝对的初学者的角度写的。我希望这是内容丰富的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: