设计模式 --- 策略模式

1,116 阅读3分钟

说明


当我们网上购物支付结算的时候,手机 app 会提示我们使用那种方式进行支付,我们选择不同的方式就会从不同的地方扣钱,这就是策略模式的应用,根据不同的选择使用不同的策略来处理同一种问题

当然,策略模式的编码方法有很多,最常用的就是 if-else 、switch 条件分支判断,如果策略过多,就会出现很多 if-else,代码很不美观,因此,使用工厂模式对策略模式进行优化,可以很好的解决这些问题

策略模式一般步骤

  1. 提取所有策略的公共接口
  2. 不同策略都实现统一公共接口
  3. 选择不同的策略来解决问题


策略模式场景演绎


下面通过网上购物的案例来一步步了解策略模式及其优化方法

首先,所有的支付方式都实现类 Pay 接口,该接口下只有一个方法, pay 

/**
 * 支付接口
 */
public interface Pay {
    void pay(int money);
}


有了这个接口,各大厂商就会实现这个接口来做出属于自己的支付软件,有 AliPay,JDPay,ApplePay 等等

public class AliPay implements Pay{
    @Override
    public void pay(int money) {
        System.out.println("使用alipay支付了" + money + "元");
    }
}

public class JDPay implements Pay{
    @Override
    public void pay(int money) {
        System.out.println("使用JDPay支付了" + money + "元");
    }
}

public class ApplePay implements Pay{
    @Override
    public void pay(int money) {
        System.out.println("使用ApplyPay支付了" + money + "元");
    }
}


有了这些支付软件,购物平台就会引进这些支付软件提供的接口,来实现多软件支付

/**
 * 网上购物app
 */
public class ShoppingApp {

    /**
     * 选择支付方式
     */
    public Pay selectPay(String payName){
        if ("aliPay".equals(payName)){
            return new AliPay();
        }else if ("JDPay".equals(payName)){
            return new JDPay();
        }else if ("applePay".equals(payName)){
            return new ApplePay();
        }else {
            return new AliPay();
        }
    }
}


最后我们写一个主函数来模拟一下线上购物的场景

public class Main {
    public static void main(String[] args) {
        ShoppingApp app = new ShoppingApp();
        Pay pay = app.selectPay("aliPay");
        pay.pay(100);
    }
}

查看控制台的输出
image.png





使用工厂模式优化


上面选择策略的过程是用 if-else 的方式来实现的,当只有很少的策略的时候,可以用这种方式,一旦策略很多,就会有很多 if-else,代码很不雅观,而且每一种策略都是 new 出来的,策略复用性不高。如果使用加入工厂模式,就会很好的解决问题

现在我们来对 ShoppingApp 进行重构,如下所示

/**
 * 网上购物app
 */
public class ShoppingApp {

    private static Map<String, Pay> payMap = new HashMap<>();

    static{
        payMap.put("aliPay", new AliPay());
        payMap.put("JDPay", new JDPay());
        payMap.put("applePay", new ApplePay());
    }


    /**
     * 选择支付方式
     */
    public Pay selectPay(String payName){
        Pay pay = payMap.get(payName);
        return Optional.ofNullable(pay).orElse(new AliPay());
    }
}


再来进行测试,查看控制台结果,同样的结果
image.png



最后


使用这种硬编码的方式将厂商实现的支持策略添加到 Map 中,确实解决了冗余的 if-else 问题,但是,代码的可扩展性不高,因为只能使用在 map 中有的策略,添加新的策略需要修改代码,不符合开闭原则。因此还可以继续优化,新建一个方法往 map 中放入新的策略,或者在配置文件中定义策略类的全限定名,使用反射来创建策略类并添加到 map 中,这样就能很好的解决