设计模式:面向对象语言开发过程中,对各种问题和场景的解决方案的沉淀 —是解决问题的套路,
提出场景–解决问题–总结沉淀–推广应用
行为型设计模式:关注对象和行为的分离
设计模式都是为了解决一类问题而存在的,往往在解决一类问题的同时会带来的新的问题,会有对应的解决方案。设计模式不是万能的。
策略模式定义
策略模式应对业务处理中,会有多种相似处理方式(算法),然后封装成算法+抽象,此外,调用环节也有扩展要求的,来个context
红色部分为稳定的,蓝色部门为变化的
代码实现
策略模式和简单工厂的结合
扩展性—抽象—反射—动态
public interface ICaculation
{
int Caculation(int iInpuLeft, int iInputRight);
}
public class Devision : ICaculation
{
public int Caculation(int iInpuLeft, int iInputRight)
{
if (iInputRight == 0) throw new Exception();
return iInpuLeft / iInputRight;
}
}
public class Minus : ICaculation
{
public int Caculation(int iInpuLeft, int iInputRight)
{
return iInpuLeft - iInputRight;
}
}
public class Mutiply : ICaculation
{
public int Caculation(int iInpuLeft, int iInputRight)
{
return iInpuLeft * iInputRight;
}
}
public class Plus : ICaculation
{
public int Caculation(int iInpuLeft, int iInputRight)
{
return iInpuLeft + iInputRight;
}
}
定义Context上下文:
/// <summary>
/// 见过哪些context,---httpcontext dbcontext callcontext
/// HttpContext,ControllerContext,ActionExecutingContext,ActionExecutedContext,ResultExecutingContext,ResulViewContexttExecutedContext,ExceptionContext,
/// 上下文环境:是为了保存整个请求过程中,全部的信息--中间结果--最终结果
/// 行为型设计模式的标配,行为会无止境的到处转移,方法需要参数。执行结果
/// 包一层:没有什么技术问题是包一层不能解决的,如果有,再包一层
/// 中间层,转移调用,核心意义就在于调用环节可以扩展
/// </summary>
public class CaculationContext
{
private ICaculation _iCaculation = null;
private int _iInpuLeft = 0;
private int _iInputRight = 0;
public CaculationContext(ICaculation caculation, int iInpuLeft, int iInputRight)
{
this._iCaculation = caculation;
this._iInpuLeft = iInpuLeft;
this._iInputRight = iInputRight;
}
private string Para = "";//可能要调用第三方接口
/// <summary>
/// 也许调用算法,需要额外的参数信息
/// </summary>
/// <returns></returns>
public int Action()
{
try
{
Console.WriteLine("Caculation");
Console.WriteLine(this.Para);
return this._iCaculation.Caculation(this._iInpuLeft, this._iInputRight);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
}
定义工厂方法:
/// <summary>
/// 面向对象语言开发从来不担心代码多,因为可以封装一下
/// 工厂只是转移了矛盾,并没有消除矛盾
/// 代码的升级是一步一步来的,先升级再解决问题,先解决眼前的问题,再解决下一步的问题
/// </summary>
public class Factory
{
/// <summary>
/// 不仅把对象创建给屏蔽了,而且映射关系也可以配置文件决定了
/// </summary>
/// <param name="operate"></param>
/// <returns></returns>
public static ICaculation GetCaculationReflection(string operate)
{
string key = $"ICaculation{operate}";
string dllType = ConfigurationManager.AppSettings[key];
Assembly assembly = Assembly.Load(dllType.Split(',')[1]);
Type type = assembly.GetType(dllType.Split(',')[0]);
return (ICaculation)Activator.CreateInstance(type);
}
}
调用方代码:
static void Main(string[] args)
{
try
{
Console.WriteLine("下面是一个计算器展示demo:");
while (true)
{
Console.WriteLine("******************************");
Console.WriteLine("******************************");
Console.WriteLine("******************************");
#region UI 前端逻辑 接受用户输入并验证
int iInputLeft = 0;
int iInputRight = 0;
string operate = "";
Console.WriteLine("输入第一个数字(整数):");
string sInputLeft = Console.ReadLine();
if (!int.TryParse(sInputLeft, out iInputLeft))
{
Console.WriteLine("输入数字无效,请重新输入");
continue;
}
Console.WriteLine("输入计算符号(+-*/):");
operate = Console.ReadLine();
string CaculationType = System.Configuration.ConfigurationManager.AppSettings["CaculationType"];
if (!CaculationType.Split(',').Contains(operate))
{
Console.WriteLine("输入计算符号无效,请重新输入");
continue;
}
Console.WriteLine("输入第二个数字(整数):");
string sInputRight = Console.ReadLine();
if (!int.TryParse(sInputRight, out iInputRight))
{
Console.WriteLine("输入数字无效,请重新输入");
continue;
}
#endregion
#region 后台逻辑 业务逻辑
int iResult = 0;
//1 转移了算法逻辑
ICaculation iCaculation = Factory.GetCaculationReflection(operate);
CaculationContext context = new CaculationContext(iCaculation, iInputLeft, iInputRight);
//2 转移了算法的调用逻辑
iResult = context.Action();
Console.WriteLine("计算为: {0}{1}{2}={3}", iInputLeft, operate, iInputRight, iResult);
#endregion
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<add key="ICaculation-" value="StrategyPattern.Service.Plus,StrategyPattern.Service"/>
<add key="ICaculation+" value="StrategyPattern.Service.Minus,StrategyPattern.Service"/>
<add key="ICaculation*" value="StrategyPattern.Service.Mutiply,StrategyPattern.Service"/>
<add key="ICaculation/" value="StrategyPattern.Service.Devision,StrategyPattern.Service"/>
<add key="CaculationType" value="+,-,*,/,%"/>
</appSettings>
</configuration>
要点总结
好处:算法封装,有抽象可以扩展;调用环节转移,可以扩展;
在代码中看到if…else…,并且其在未来是变化的,就应该考虑是否可以采用Strategy模式!!!