战略形式又叫做政策形式,他是将界说的算法家族、别离封装起来,让他们之间能够彼此替换,然后让算法的改变不会影响到运用算法的用户,属于行为型形式。
战略形式运用的就是面向对象的继承和多态机制,从未完成同一行为在不同场景下具有不同完成。
浅显点将就是在咱们事务逻辑中很定有许多switch case
或者是许多if else
,咱们的事务是需求经过场景判断挑选其间一个逻辑执行,这个时分就能够运用战略形式(需求留意的是战略形式一定是只需求执行许多逻辑算法中的一个,而不是执行多个逻辑算法,如果是执行多个就不太合适运用战略形式)
战略形式的运用场景
举一个很常见的例子:付出。
咱们接入不同的付出必定是需求运用不同的sdk, 付出宝运用的是付出宝的sdk,微信运用的是微信的sdk。咱们在付出的时分必定只能挑选一种办法付出,这个时分就比较合适运用战略形式.
总结一下:战略形式适用场景:
- 针对一个问题有多个不同的处理办法,每种办法之间没有耦合(能够独立解决问题)
- 算法逻辑需求自在切换的情况下
- 需求屏蔽算法逻辑规矩的场景(应为高层是不接触算法逻辑的完成的)
咱们能够看一下战略形式通用的UML类图: 其间:
- 上下文人物(Context):主要运用来操作战略上下文,做到屏蔽高层模块对战略、算法直接访问,也能够在这儿封装可能存在的改变
- 笼统战略人物(Strategy):主要是规定战略或者算法的行为
- 详细战略人物(ConcreteStrategy):战略或者是算法的完成
付出事例完成(无规划形式情况下)
package com.example.demo.test.pay;
import java.util.Objects;
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public void pay(String payType){
int currentAmount = 0;
if(Objects.equals(payType, "AliPay")){
//这儿需求查询付出宝账户余额然后
currentAmount = 900;
if(this.amount > currentAmount){
System.out.println("付出宝余额缺乏");
return;
}
//调用付出宝SDK付出
System.out.println("付出宝-付出成功");
}else if(Objects.equals(payType, "WeChatPay")){
//这儿需求查询付出宝账户余额然后
currentAmount = 600;
if(this.amount > currentAmount){
System.out.println("微信余额缺乏");
return;
}
//调用付出宝SDK付出
System.out.println("微信-付出成功");
}else if(Objects.equals(payType, "UnionPay")){
currentAmount = 100;
if(this.amount > currentAmount){
System.out.println("银行卡余额缺乏");
return;
}
System.out.println("银行卡-付出成功");
}
}
}
public class Test {
public static void main(String[] args) {
Order order = new Order("123123", "333222", 977);
order.pay("AliPay");
}
}
这样规划的优点感觉一眼就能看出来,许多的付出逻辑都耦合在订单的模块,这样今后的保护和修正都很难,代码只会越来越低最后堆成屎山。
咱们也能够发现这个付出就很合适运用战略形式,应为不行能有某个订单运用联合付出,所以咱们在运用纯战略形式更改一下
付出事例完成(战略规划形式)
package com.example.demo.test.pay;
import java.util.Objects;
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public void pay(String payType){
if(Objects.equals(payType, "AliPay")){
AliPay aliPay = new AliPay();
PayContext payContext = new PayContext(aliPay);
payContext.pay(this.uid, this.amount);
}else if(Objects.equals(payType, "WeChatPay")){
WeChatPay weChatPay = new WeChatPay();
PayContext payContext = new PayContext(weChatPay);
payContext.pay(this.uid, this.amount);
}else if(Objects.equals(payType, "UnionPay")){
UnionPay unionPay = new UnionPay();
PayContext payContext = new PayContext(unionPay);
payContext.pay(this.uid, this.amount);
}
}
}
public interface IPay {
String getName();
Double queryBalance(String uid);
default void pay(String uid,Double price){
Double currentAmount = queryBalance(uid);
if(currentAmount < price){
System.out.println(getName() + "余额缺乏");
}else{
System.out.println(getName() + "付出成功");
}
}
}
package com.example.demo.test.pay;
public class AliPay implements IPay{
@Override
public String getName() {
return "付出宝";
}
@Override
public Double queryBalance(String uid) {
return 900.0;
}
}
package com.example.demo.test.pay;
public class WeChatPay implements IPay{
@Override
public String getName() {
return "微信付出";
}
@Override
public Double queryBalance(String uid) {
return 200.0;
}
}
package com.example.demo.test.pay;
public class UnionPay implements IPay{
@Override
public String getName() {
return "银行卡";
}
@Override
public Double queryBalance(String uid) {
return 10000.0;
}
}
咱们能够先看他一下UML类图:
发现和上文提到战略形式的UML类图是相同的。可是咱们在看详细的代码完成虽然咱们说是将付出的算法逻辑完成抽离出来了,代码是比第一种完成办法要简洁一些了,可是仍是省不掉if...else
,所以说规划形式是一个规划代码的理念,详细到完成仍是需求切合实际考虑比如要考虑详细的事务完成逻辑(当然付出这个事务逻辑仍是很合适运用战略形式的),还有就是各个规划形式之间的交融。接下来咱们在运用战略形式+单例形式+工厂形式再改造一下
付出事例完成(战略规划形式+单例+工厂形式)
package com.example.demo.test.pay;
import java.util.Objects;
public class Order {
private String uid;
private String orderId;
private double amount;
public Order(String uid, String orderId, double amount) {
this.uid = uid;
this.orderId = orderId;
this.amount = amount;
}
public void pay(String payType){
IPay iPay = PayFactory.getMethod(payType);
PayContext payContext = new PayContext(iPay);
payContext.pay(this.uid, this.amount);
}
}
package com.example.demo.test.pay;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class PayFactory {
private static final Map<String,IPay> METHOD = new HashMap<>();
static {
METHOD.put(MethodKey.ALIPAY,new AliPay());
METHOD.put(MethodKey.WECHAT_PAY,new WeChatPay());
METHOD.put(MethodKey.UNION_PAY,new UnionPay());
}
private interface MethodKey {
String ALIPAY = "ALIPAY";
String WECHAT_PAY = "WECHAT_PAY";
String UNION_PAY = "UNION_PAY";
}
private static final IPay defaultPay = new AliPay();
public static IPay getMethod(String key){
if(METHOD.containsKey(key)){
return METHOD.get(key);
}
return defaultPay;
}
public static Set<String> getMethodKey(){
return METHOD.keySet();
}
}
其他的都不变咱们只需求添加一个工厂类,咱们能够界说好Map
,经过type找到对应的map就能够完美完成了,咱们再看一下order的代码这个时分就会发现很赶忙,很优雅,咱们先修正某一个付出办法只需求到详细类修正就行,不需求在反复修正order中的pay办法,也契合了开闭准则。
当然这儿也能够直接不要Context个人觉得也能够详细看自己的事务吧,活学活用