今天就说一说设计模式中的策略模式,从名字来讲,意思就是,对应不同的情况,就有一种解决问题的办法,不同的情况,就有不同的应对方法,这就是策略模式,非常的智能化。
也可以参考菜鸟
1.下面我们看一组经常会写到的代码
尤其在业务场景非常复杂的逻辑中,经常出现大量的if语句,包括switch语句,不过switch稍微比if语句好点。
namespace StrategyPatternDemo
{
internal class Program
{
static void Main(string[] args)
{
string a = Console.ReadLine().ToString();
if (a == "a")
{
a = "A";
//业务
}
else if (a == "b")
{
a = "B";
//业务
}
else if (a == "c")
{
a = "C";
//业务
}
else if (a == "d")
{
a = "D";
//业务
}
else if (a == "e")
{
a = "E";
//业务
}
else if (a == string.Empty)
{
a = "空";
//业务
}
Console.WriteLine(a);
Console.ReadKey();
}
}
}
该代码要实现的业务就是,输入小写字母,然后输出大写字母,再处理一些业务员需求,当然也可以ToUpper方法,就可以了,我们不做讨论,主要是要采用策略模式来设计一下(当然这个也算是过度设计了)。代码简洁、有效、实现功能才是最好的代码。
2.接下来,我们使用策略模式
TypeSelect类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StrategyPatternDemo
{
/// <summary>
/// 业务类型,后面继续加
/// </summary>
public enum TypeSelect
{
A = 1,
B = 2,
C = 3,
D = 4,
E = 5,
Empty = 6,
}
}
2.StrategyPatternDemo类,定义公共接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StrategyPatternDemo
{
/// <summary>
/// 定义一个公开的接口
/// </summary>
public interface IStrategy
{
void Execute(string str);
}
}
3.StrategyPatternDemo类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace StrategyPatternDemo
{
/// <summary>
/// 增加实例
/// </summary>
/// <typeparam name="T"></typeparam>
public class InstanceFactory<T> where T : class
{
private static Dictionary<TypeSelect, T> dicCommands = new Dictionary<TypeSelect, T>();
public T CreateInstanceByEnumName(TypeSelect taskType)
{
foreach (TypeSelect cd in Enum.GetValues(typeof(TypeSelect)))
{
if (!dicCommands.Keys.Contains(cd))
{
//此处获取业务类的种类,可以使用其他方法
T baseCommand = Assembly.Load(typeof(T).Assembly.GetName().Name).CreateInstance((typeof(T).Namespace + ".Business.StrategyBusiness" + cd)) as T;
if (baseCommand != null)
{
dicCommands.Add(cd, baseCommand);
}
}
}
return dicCommands.FirstOrDefault(c => c.Key == taskType).Value;
}
}
}
4.StrategyPatternDemo类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StrategyPatternDemo
{
/// <summary>
/// 一般写法
/// </summary>
internal class Context
{
private IStrategy _strategy;
public Context(IStrategy strategy)
{
_strategy = strategy;
}
public void ExecuteStrategy(string str)
{
_strategy?.Execute(str);
}
}
}
5.业务类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StrategyPatternDemo.Business
{
internal class StrategyBusinessA : IStrategy
{
public void Execute(string s)
{
Console.WriteLine(s);
//其他业务
}
}
}
6.调用
可见,调用只需要一句话
using StrategyPatternDemo.Business;
namespace StrategyPatternDemo
{
internal class Program
{
static void Main(string[] args)
{
//string a = Console.ReadLine().ToString();
//if (a == "a")
//{
// a = "A";
// //业务
//}
//else if (a == "b")
//{
// a = "B";
// //业务
//}
//else if (a == "c")
//{
// a = "C";
// //业务
//}
//else if (a == "d")
//{
// a = "D";
// //业务
//}
//else if (a == "e")
//{
// a = "E";
// //业务
//}
//else if (a == string.Empty)
//{
// a = "空";
// //业务
//}
//Console.WriteLine(a);
//Console.ReadKey();
int a = Convert.ToInt32(Console.ReadLine());
var str = (TypeSelect)a; //转化类型
new Context(new InstanceFactory<IStrategy>().CreateInstanceByEnumName(str)).ExecuteStrategy(str.ToString()); //调用
Console.ReadKey();
}
}
}
7.效果
8.增加F
只需要增加2处,其他地方不变
效果
9.文件总览
此文,只是为了策略模式而策略模式,设计模式在日常的开发代码中,很少使用,比如以上案例,使用设计模式,就太复杂了, 根本没必要使用。但是在用到的时候,将会非常的给力,大部分都是后期业务堆起来后,才会体现出设计模式优点,当然使用了设计模式,也有缺点,一切的一切,都按照当下的业务量来衡量,是否有必要使用设计模式。
其中ConsoleApp1是另一种方式实现,效果一样
源码: