策略模式
1 定义
该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以乘坐飞机、乘坐火车、骑自行车或自己开私家车等,超市促销可以釆用打折、送商品、送积分等方法。
2 模式的结构
抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
环境(Context)类:持有一个策略类的引用,最终给客户端调用。
3 实现
3.1 引入
电商平台在执行支付这个操作的时候,会有很多种选择支付方式,常见的一种代码是
if (Objects.equals(paymentWay, "支付宝")) {
支付宝支付处理逻辑...
} else if (Objects.equals(paymentWay, "微信")) {
微信支付处理逻辑...
} else if (Objects.equals(paymentWay, "银联云闪付")) {
银联云闪付支付处理逻辑...
}
看看上面的代码是不是觉得头晕胸闷。每个 if else 中都有大量的逻辑处理,新增一个支付方式,就需要新增一个 if else ,这样写了之后,不仅代码的可读性低,而且后期的维护成本也是大大的增高了。而且每次的修改出错的几率也是比较高。
3.2 定义支付接口
//支付方式
public interface Payment {
void payment();
}
3.3 支付宝支付实现
public class AliPayPayment implements Payment {
@Override
public void payment() {
System.out.println("支付宝支付");
}
}
3.4 微信支付实现
public class WechatPayPayment implements Payment {
@Override
public void payment() {
System.out.println("微信支付");
}
}
3.5 银联云闪付
public class UnionPayPayment implements Payment {
@Override
public void payment() {
System.out.println("银联云闪付");
}
}
3.6 环境类定义(将策略注入进去)
public class PaymentContext {
private Payment payment;
public PaymentContext(Payment payment) {
this.payment = payment;
}
public void payment(){
payment.payment();
}
}
3.7 测试
class Test {
public static void main(String[] args) {
//支付宝支付
PaymentContext aliPay = new PaymentContext(new AliPayPayment());
aliPay.payment();
//微信支付
PaymentContext wechatPay = new PaymentContext(new WechatPayPayment());
wechatPay.payment();
//银联云闪付
PaymentContext unionPay = new PaymentContext(new UnionPayPayment());
unionPay.payment();
}
}
3.8 结果
支付宝支付
微信支付
银联云闪付
4 优缺点和使用场景
4.1 优点
-
策略类之间可以自由切换
由于策略类都实现同一个接口,所以使它们之间可以自由切换。
-
易于扩展
增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“
-
避免使用多重条件选择语句(if else),充分体现面向对象设计思想。
4.2 缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
- 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。
4.3 使用场景
- 一个系统需要动态地在几种算法中选择一种时,可将每个算法封装到策略类中。
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句。
- 系统中各算法彼此完全独立,且要求对客户隐藏具体算法的实现细节时。
- 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构。
- 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为。
5 策略模式的扩展
在一个使用策略模式的系统中,当存在的策略很多时,客户端管理所有策略算法将变得很复杂,如果在环境类中使用策略工厂模式来管理这些策略类将大大减少客户端的工作复杂度