如果在开发过程中,出现大量的if else或者switch case 语句,如果这些语句块中的代码并不是包含业务逻辑,只是单纯的分流方法,那么,每一个语句块中都是一个算法或者叫策略。
背景
比如在最近项目中遇到的问题。一个二维码字符串解析的方法:
微信的二维码扫描结果包含“WeChat”,解析规则是拿着文本到微信服务器解析,返回解析对象。
支付宝二维码扫描结果包含“Alipay”,解析规则是使用“->”分割字符串得到解析对象。
最简单快速的代码就是直接if else判断:
1 /// <summary> 2 /// 解析方法 3 /// </summary> 4 /// <param name="text">扫描得到的文本</param> 5 public void AnalysisAction(string text) 6 { 7 //微信解析方法 8 if (text.Contains("WeChat")) 9 { 10 //拿着text到微信服务器解析,返回解析对象。 11 } 12 //支付宝解析方法 13 else if (text.Contains("Alipay")) 14 { 15 //使用->分割,得到解析对象。 16 } 17 }
问题
当然使用这种方式是可以的,但是如果以后又加入一种扫码解析方法:
中国联通二维码扫描文本中包含“Unicom”,解析规则为以“:”分割,得到解析对象。
那么你就要继续添加else if(text.Contains("Unicom"))。每次增加一个新的扫描解析规则,你都要去增加else if判断,这种是面向过程的体验,属于硬编码。这也违反了面向对象的开闭原则。
改进(抽象)
我们可以使用策略模式来改进代码。定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
抽象出一个扫描解析接口,定义一个解析方法。然后分别定义微信和支付宝的解析方法集成接口。
策略模式的uml图如下:
/// <summary> /// 扫描解析规则抽象接口 /// </summary> public interface IStrategy { /// <summary> /// 扫描解析方法策略 /// </summary> /// <param name="text"></param> void AnalysisAction(string text); }