示例
想象一种场景,有一个方法用于支付请求,调用者需要传入很多种不同的支付类型,然后该方法使用对应的支付产品进行支付操作,先看下糟糕的实现
糟糕的代码实现
//差的代码设计,调用端和实现端紧耦合,因为pay type还可能不断增加,那么每次都需要修改switch语言
public void Pay_BadPractice(PayType payType)
{
switch (payType)
{
case PayType.Ali:
{
Console.WriteLine("使用了支付宝进行支付");
}; break;
case PayType.WeChat:
{
Console.WriteLine("使用了微信进行支付");
}; break;
case PayType.BankCard:
{
Console.WriteLine("使用了银联进行支付");
}; break;
}
}
标准的策略模式
public void Pay_GoodPractice(PayType payType)
{
//标准策略模式
//即使用了策略模式,你该写的业务逻辑照常写,到逻辑分派的时候,还是变相的if else。而它的优化点是抽象了出了接口,将业务逻辑封装成一个一个的实现类,任意地替换。在复杂场景(业务逻辑较多)时比直接 if else 来的好维护些。
switch (payType)
{
case PayType.Ali:
{
IPay pay = new AliPay();
Context ct = new Context(pay);
ct.doAction();
}; break;
case PayType.WeChat:
{
IPay pay = new WeChatPay();
Context ct = new Context(pay);
ct.doAction();
}; break;
case PayType.BankCard:
{
IPay pay = new BankCardPay();
Context ct = new Context(pay);
ct.doAction();
}; break;
}
}
public enum PayType
{
Ali,
WeChat,
BankCard
}
//策略模式有三个组成角色:
//抽象策略(Strategy)类
//具体策略(Concrete Strategy)类
//环境(Context)类
//抽象策略角色
public interface IPay
{
static PayType payType { get; }
void Pay();
}
//具体实现策略角色
public class AliPay : IPay
{
public static PayType payType
{
get
{
return PayType.Ali;
}
}
public void Pay()
{
Console.WriteLine("使用了支付宝进行支付");
}
}
public class WeChatPay : IPay
{
public static PayType payType
{
get
{
return PayType.WeChat;
}
}
public void Pay()
{
Console.WriteLine("使用了微信进行支付");
}
}
public class BankCardPay : IPay
{
public static PayType payType
{
get
{
return PayType.BankCard;
}
}
public void Pay()
{
Console.WriteLine("使用了银联进行支付");
}
}
//Context统一管理具体实现策略的调用
public class Context
{
IPay pay;
public Context(IPay pay)
{
this.pay = pay;
}
//暴露给调用端的接口
public void doAction()
{
this.pay.Pay();
}
}
改良版策略模式1.0(使用字典消除if else)
//改良策略模式1,可在Context里的使用字典
public class ContextWithDic
{
static Dictionary<PayType, IPay> dicPay = new Dictionary<PayType, IPay>();
static ContextWithDic()
{
dicPay.Add(PayType.Ali, new AliPay());
dicPay.Add(PayType.WeChat, new WeChatPay());
dicPay.Add(PayType.BankCard, new BankCardPay());
}
//暴露给调用端的接口
public void doAction(PayType payType)
{
dicPay[payType].Pay();
}
}
public void Pay_GoodPractice(PayType payType)
{
//改良策略模式1,可在Context里的使用字典完全消除条件判断,缺点是每次增加新的pay策略时,需要在Context里同步增加到字典里
new ContextWithDic().doAction(payType);
}
改良版策略模式2.0(使用反射消除if else)
public class ContextWithReflection
{
static Dictionary<PayType, IPay> dicPay = new Dictionary<PayType, IPay>();
static ContextWithReflection()
{
var ass = Assembly.Load("DesignPatterns");
Type[] types = ass.GetTypes();
foreach (var item in types)
{
if (typeof(IPay).IsAssignableFrom(item) && item != typeof(IPay))//判断该类型是否实现了IPay接口且不是IPay本身
{
var instance = Activator.CreateInstance(item);
var payTypeProperty = item.GetProperty("payType", BindingFlags.Public | BindingFlags.Static);//获取静态属性payType的值
dicPay.Add((PayType)payTypeProperty.GetValue(instance, null), (IPay)instance);
}
}
}
//暴露给调用端的接口
public void doAction(PayType payType)
{
dicPay[payType].Pay();
}
}
public void Pay_GoodPractice(PayType payType)
{
//改良策略模式2,利用反射自动将新的pay策略增加到字段里,无需修改Context类
new ContextWithReflection().doAction(payType);
}