C#设计模式之Strategy策略模式解决007大破密码危机问题示例
策略模式介绍
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互相替换。
策略模式的实现方法
在策略模式中,定义一个具体的策略接口(抽象类),接口中定义公共的方法(通用的算法),具体的策略类实现这个接口,实现各自的算法。在程序中定义一个Context类,该类中有一个私有成员变量strategy,它是一个父级策略类,Context类中有一个用来设置策略的方法setStrategy和一个用来执行策略的方法executeStrategy。通过调用setStragety方法可以动态地选择不同的策略。
策略模式的使用场景
策略模式主要用于解决许多算法彼此之间只有细微的不同的问题。就像一个类拥有无数的方法一样,但是许多方法只是细微的不同点,这时候就可以用策略模式将这些不同点定义为一个接口,然后在每个具体实现中实现自己的算法。这样将代码封装之后,代码就易于维护和扩展。通常用策略模式来解决算法的切换问题。
Strategy策略模式解决007大破密码危机问题示例
假设在007电影中,恶势力组织需要对MI6总部的密码进行攻击,他们知道密码是用凯撒密码加密的,只有一个生成密钥的秘密方法。Bond无法破解秘密方法,所以他需要写一个破解程序,采用Strategy策略模式解决问题。
我们先定义一个接口ICodeStrategy
,然后定义一个抽象类CodeStrategy
,它实现了ICodeStrategy
接口中的所有方法,并且提供了一个密钥生成函数GenerateKey()
,其他具体的策略类都是从CodeStrategy
基类中派生出来的。
public interface ICodeStrategy
{
string Encrypt(string plain, string key);
string Decrypt(string cipher, string key);
}
public abstract class CodeStrategy : ICodeStrategy
{
public string Encrypt(string plain, string key)
{
return DoEncrypt(plain, key);
}
public string Decrypt(string cipher, string key)
{
return DoDecrypt(cipher, key);
}
protected abstract string DoEncrypt(string plain, string key);
protected abstract string DoDecrypt(string cipher, string key);
public virtual string GenerateKey()
{
return Guid.NewGuid().ToString().Substring(0, 8);
}
}
下面是凯撒密码的加密解密算法实现,即从CodeStrategy
基类中派生出来的策略类CaesarCodeStrategy
和ReverseCodeStrategy
:
public class CaesarCodeStrategy : CodeStrategy
{
protected override string DoEncrypt(string plain, string key)
{
int shift = int.Parse(key);
StringBuilder result = new StringBuilder();
foreach (char c in plain)
{
if (char.IsLetter(c))
{
if (char.IsUpper(c))
result.Append((char)('A' + (c - 'A' + shift) % 26));
else
result.Append((char)('a' + (c - 'a' + shift) % 26));
}
else
{
result.Append(c);
}
}
return result.ToString();
}
protected override string DoDecrypt(string cipher, string key)
{
int shift = int.Parse(key);
StringBuilder result = new StringBuilder();
foreach (char c in cipher)
{
if (char.IsLetter(c))
{
if (char.IsUpper(c))
result.Append((char)('A' + (c - 'A' - shift + 26) % 26));
else
result.Append((char)('a' + (c - 'a' - shift + 26) % 26));
}
else
{
result.Append(c);
}
}
return result.ToString();
}
}
public class ReverseCodeStrategy : CodeStrategy
{
protected override string DoEncrypt(string plain, string key)
{
char[] charArray = plain.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
protected override string DoDecrypt(string cipher, string key)
{
char[] charArray = cipher.ToCharArray();
Array.Reverse(charArray);
return new string(charArray);
}
}
最后,我们定义一个Context类CodeContext
:
public class CodeContext
{
private readonly ICodeStrategy _strategy;
public CodeContext(ICodeStrategy strategy)
{
_strategy = strategy;
}
public void SetStrategy(ICodeStrategy strategy)
{
_strategy = strategy;
}
public string GenerateKey()
{
return _strategy.GenerateKey();
}
public string ExecStrategy(string plain, string key)
{
return _strategy.Encrypt(plain, key);
}
public string UnexecStrategy(string cipher, string key)
{
return _strategy.Decrypt(cipher, key);
}
}
现在,我们可以创建一个CodeContext
对象,设置一个策略类,然后执行该策略类的密钥生成和加密过程:
CodeContext context = new CodeContext(new CaesarCodeStrategy());
string plain = "mi6headquarters";
string key = context.GenerateKey();
string cipher = context.ExecStrategy(plain, key);
Console.WriteLine("plain: {0}", plain);
Console.WriteLine("key: {0}", key);
Console.WriteLine("cipher: {0}", cipher);
执行结果如下:
plain: mi6headquarters
key: 3c76ada6
cipher: pl9ealikxkmexiyoi
接下来,我们可以用同样的过程执行秘钥解密过程。
string plain2 = context.UnexecStrategy(cipher, key);
Console.WriteLine("cipher2: {0}", cipher);
Console.WriteLine("key2: {0}", key);
Console.WriteLine("plain2: {0}", plain2);
执行结果如下:
cipher2: pl9ealikxkmexiyoi
key2: 3c76ada6
plain2: mi6headquarters
由此看来,通过Strategy策略模式,我们可以方便地实现算法类的扩展和修改。而且,通过上述方法是不需要进行大量的代码修改和重构的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#设计模式之Strategy策略模式解决007大破密码危机问题示例 - Python技术站