最近段时间,接到一个需求:开发一个聚合支付服务,对其他内部项目提供统一的接口来实现不同支付平台的支付能力发起,比如支付宝,微信,银联等。为了处理相似的支付操作而各平台具体实现不同的情况,要让各个平台接口能力能相互独立,并要方便扩展后续新增的支付平台,我引入了设计模式的策略模式来应对需求场景,借此深入学习总结下策略模式,于是也就有了本文,希望对学习策略模式的同学有所帮助。
为什么需要策略模式日常工作开发中我们总会遇到如下熟悉的代码片段:
if(condition1){ // do something1 } else if (condition2){ // do something2 } else if (condition3){ // do something3 }在每个 if 条件下都有数十行甚至百行的业务处理,各自处理又是相互独立的并且目的一致,都汇聚在一个方法里。这样的写法不但让类变得臃肿冗长,并且不同逻辑都在一个类中修改,维护和扩展起来都很费劲。那么又有什么办法可以优化这大段的代码呢,在实现功能的同时,让代码更加灵活和易维护。
要解决这个问题,本文的主角—策略模式 就登场了,作为设计模式中比较简单的行为型模式,其实很多框架中都见到它的身影,稍后我们也会从各框架源码中识别策略模式的应用。使用策略模式可以帮助我们将每个处理逻辑封装成独立的类,客户端类需要进行哪种处理逻辑就使用对应的类,调用其封装了业务处理细节的方法即可。这样一来,客户端类减少了业务处理逻辑的大量代码,让自身更加精简。当业务逻辑有所改动时,只要在对应的类中修改,而不影响其他的类;并且如果出现了新的业务逻辑只要新增相似的类进行实现,供客户端类调用即可。
什么是策略模式接下来我们就介绍下策略模式的定义和组成,以及它的基本形式。
首先看下维基百科上策略模式的定义:
In computer programming, the strategy pattern (also known as the policy pattern) is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.
策略模式也叫政策模式,允许程序在运行时选择一个算法执行,通常存在一类算法实现提供外部选择执行,这里的算法,也可以叫做策略,相当于上节内容提到的具体处理逻辑。
再来看下 《设计模式:可复用面向对象软件的基础》一书中对策略模式的定义:
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.
再次对其定义解读:定义一类算法,各自独立封装实现,并且相互之间是可替换的。除此之外,由客户端类决定具体使用哪个算法。
上述两个定义都提到了算法一词,它表示了完整的,不可再拆分的业务逻辑处理。通常用接口或者抽象类来表示一类算法的抽象,提供多种对该类算法的操作实现,以此组成一类独立且可替换的算法,也叫策略组。
了解完定义后,我们再来看下策略模式通用类图:
类图中涉及三类角色:Context,Strategy 和 ConcreteStrategy
Strategy:抽象策略角色,代表某个算法的接口或者抽象类,定义了每个算法或者策略需要具有的方法和属性。
Context:上下文角色,引用策略接口对象,屏蔽了外部模块对策略或方法的直接访问,只能通过Context 提供的方法访问。
ConcreteStrategy:抽象策略的具体实现,该类含有具体的算法,并且通常不只一种实现,有多个类。
这三个角色的功能职责都十分明确,对应的源码实现也十分简单,现在我们就来快速看下每个角色对应的通用源码。
// 抽象的策略角色 public interface Strategy { void doSomething(); } // 具体策略角色 public class ConcreteStrategy implements Strategy { @Override public void doSomething() { System.out.println("ConcreteStrategy doSomething !"); } } // 上下文角色 public class Context { private final Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void doAnything() { this.strategy.doSomething(); } }有了策略模式的基本代码结构,在客户端类中使用十分简单,想要哪个策略,就产生出它的具体策略对象放入上下文对象内,然后由上下文对象执行具体策略操作即可,具体代码如下:
public class Client { public static void main(String[] args) { Strategy strategy = new ConcreteStrategy(); Context context = new Context(strategy); context.doAnything(); // ConcreteStrategy doSomething ! } } 识别策略模式