策略(Strategy)模式:
用意是定义一组算法,把它们一个个封装起来,并且使他们可以相互替换。这样策略模式就可以独立使用它们的客户端变化。
由此可以看出策略模式是由三部分自称的。
1、抽象策略(Strategy)角色:是抽象类或接口来承担,它给出具体策略角色需要实现的接口;
2、具体策略(ConcreteStrategy)角色:实现封装了具体的算法或行为;
3、场景(Context)角色:持有抽象策略类的引用。
因此策略模式的中点是:封装不同的算法和行为,不同的场景下可以相互替换,很好地解决else if的问题。
实例分析:
某支付系统接入以下几种商户进行充值:易宝网易,快线网银,支付宝支付,财付通等
由于每家充值系统的结算比例不一样,而且 同一家商户的不同充值方式也有所不同。 已支付宝为例的话, 大哥比方其有四种支付方式:手机支付,网银支付,商户账号支付和点卡支付。 这四种支付方式的手续费是不一样的, 比如:
①网银充值,8.5折;
②商户充值,9折;
③手机充值,没有优惠;
④点卡充值,收取1%的渠道费;
在没有使用模式的情况写的代码:
package strategy;
public class Example {
public Double calRecharge(Double charge ,RechargeTypeEnum type ){
if(type.equals(RechargeTypeEnum.E_BANK)){
return charge*0.85;
}else if(type.equals(RechargeTypeEnum.BUSI_ACCOUNTS)){
return charge*0.90;
}else if(type.equals(RechargeTypeEnum.MOBILE)){
return charge;
}else if(type.equals(RechargeTypeEnum.CARD_RECHARGE)){
return charge+charge*0.01;
}else{
return null;
}
}
}
可以看出:四种不同的计算方式在一个方法内部,不利于扩展和维护,当然也不符合面向对象设计原则。对以上的代码利用策略模式进行修改
现在使用策略模式: 图如下。
1):
<span style="font-size:18px;">package strategy.strategy;
import strategy.RechargeTypeEnum;
public interface Strategy {
public Double calRecharge(Double charge ,RechargeTypeEnum type );
}</span>
2):<pre name="code" class="java"><span style="font-size:18px;">package strategy.strategy;
import strategy.RechargeTypeEnum;
public class EBankStrategy implements Strategy{
@Override
public Double calRecharge(Double charge, RechargeTypeEnum type) {
return charge*0.85;
}
<span style="font-size:18px;">package strategy.strategy;
import strategy.RechargeTypeEnum;
public class BusiAcctStrategy implements Strategy{
@Override
public Double calRecharge(Double charge, RechargeTypeEnum type) {
// TODO Auto-generated method stub
return charge*0.90;
<span style="font-family: Arial, Helvetica, sans-serif;">}</span>
<span style="font-size:18px;">package strategy.strategy;
import strategy.RechargeTypeEnum;
public class MobileStrategy implements Strategy {
@Override
public Double calRecharge(Double charge, RechargeTypeEnum type) {
// TODO Auto-generated method stub
return charge;
}
}</span>
package strategy.strategy;
import strategy.RechargeTypeEnum;
public class CardStrategy implements Strategy{
@Override
public Double calRecharge(Double charge, RechargeTypeEnum type) {
return charge+charge*0.01;
}
}
3):
package strategy.strategy;
import strategy.RechargeTypeEnum;
public class Context {
private Strategy strategy;
public Double calRecharge(Double charge, Integer type) {
strategy = StrategyFactory.getInstance().creator(type);
return strategy.calRecharge(charge, RechargeTypeEnum.valueOf(type));
}
public Strategy getStrategy() {
return strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;}
4)
package strategy.strategy;
import java.util.HashMap;
import java.util.Map;
import strategy.RechargeTypeEnum;
public class StrategyFactory {
private static StrategyFactory factory = new StrategyFactory();
private StrategyFactory(){
}
private static Map strategyMap = new HashMap<>();
static{
strategyMap.put(RechargeTypeEnum.E_BANK.value(), new EBankStrategy());
strategyMap.put(RechargeTypeEnum.BUSI_ACCOUNTS.value(), new BusiAcctStrategy());
strategyMap.put(RechargeTypeEnum.MOBILE.value(), new MobileStrategy());
strategyMap.put(RechargeTypeEnum.CARD_RECHARGE.value(), new CardStrategy());
}
public Strategy creator(Integer type){
return strategyMap.get(type);
}
public static StrategyFactory getInstance(){
return factory;
}
}
5):
package strategy.strategy;
import strategy.RechargeTypeEnum;
public class Client {
public static void main(String[] args) {
Context context = new Context();
// 网银充值100 需要付多少
Double money = context.calRecharge(100D,
RechargeTypeEnum.E_BANK.value());
System.out.println(money);
// 商户账户充值100 需要付多少
Double money2 = context.calRecharge(100D,
RechargeTypeEnum.BUSI_ACCOUNTS.value());
System.out.println(money2);
// 手机充值100 需要付多少
Double money3 = context.calRecharge(100D,
RechargeTypeEnum.MOBILE.value());
System.out.println(money3);
// 充值卡充值100 需要付多少
Double money4 = context.calRecharge(100D,
RechargeTypeEnum.CARD_RECHARGE.value());<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(240, 240, 240);">System.out.println(money4);</span></span>
}
}
通过上图我们看到: 策略模式把具体的算法封装到了具体策略角色内部,增强了可扩展性。
1、抽象策略(Strategy)角色