策略模式消除恶心的if else

一 . 什么是策略模式

   策略模式是对算法的包装,把使用算法的责任和算法本身分隔开,委派给不同的对象管理。策略模式通常把一系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。

   简单来说就是就定义一个策略接口,子类策略去实现该接口去定义不同的策略。然后定义一个环境(Context)类,以策略接口作为成员变量,根据环境来使用具体的策略。

 

二. 使用场景

         业务中有要根据不同条件来使用不同算法的情况下,并且这些算法可以抽象的,就可以去使用。例如说,根据用户的分类,可以分为普通用户、白金用户、钻石用户等,不同种类的用户结算时需要不同的结算算法。如果不使用的话,那么可能造成每增加用户种类就需要去,就要在业务代码上去增加一个判断,造成的后果就是代码越来越冗余,不利于维护,也不方便阅读。

三. 如何使用

     1.定义策略接口

1 public interface Strategy {
2 
3     public Double count(Double pay);
4 }

   2.不同策略实现该策略接口

//普通会员 全款
public class StrategyNormal implements Strategy {

    @Override
    public Double count(Double pay) {
        return pay ;
    }
}

//白金会员98折
public class StrstegyPlatinum implements Strategy {
    @Override
    public Double count(Double pay) {
        return pay * 0.98;
    }
}

//钻石会员9折

public class StrstegyDiamond implements Strategy {
    @Override
    public Double count(Double pay) {
        return pay * 0.9;
    }
}

3.定义策略环境

public class Context {

    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }


    public Double count(Double pay){
        return strategy.count(pay);
    }

 

4.定义策略工厂

   为什么有策略工厂?因为在策略环境Context 中需要具体的策略实现类去进行算法计算的,所以需要根据客户端给出的条件去具体的拿到策略类。

   首先我们定义一个枚举类,定义不同的用户级别

  

public enum CustomerType {

    NORMAL(0,"普通用户"),

    PLATINUM(1,"白金用户"),

    DUAMOND(2,"钻石用户");

    private int index;

    private String message;

    CustomerType(int index, String message) {
        this.index = index;
        this.message = message;
    }

    @Override
    public String toString() {
        return "CustomerType{" +
                "index=" + this.index +
                ", message='" + this.message + '\'' +
                '}';
    }

定义具体的策略工厂,工厂类一般定义为单例,防止创建多个对象。这里使用双重校验的懒模式。

public class StrategyFactory {

    private volatile static StrategyFactory strategyFactory;

    private static Map<CustomerType,Strategy> strstegyMap = new HashMap<CustomerType,Strategy>();

    static {
        strstegyMap.put(CustomerType.NORMAL ,new StrategyNormal());

        strstegyMap.put(CustomerType.PLATINUM,new StrstegyPlatinum());

        strstegyMap.put(CustomerType.DUAMOND,new StrstegyDiamond());
    }

    private StrategyFactory() {

    }

    public static  Strategy getInstance(CustomerType type){
        if (strategyFactory == null) {
            synchronized (StrategyFactory.class) {
                if (strategyFactory == null){
                    strategyFactory = new StrategyFactory();
                }
            }
        }
        return strategyFactory.strstegyMap.get(type);
    }

}
View Code

 

5.调用

public static void main(String[] args) {

        Double pay = 100.00D;

        Strategy strategyNormal = StrategyFactory.getInstance(CustomerType.NORMAL);
        Context contextNormal  = new Context(strategyNormal);
        System.out.println(CustomerType.NORMAL.toString() + "应付:" + contextNormal.count(pay));

        Strategy strategyPlatinum = StrategyFactory.getInstance(CustomerType.PLATINUM);
        Context contextPlatinum  = new Context(strategyPlatinum);
        System.out.println(CustomerType.PLATINUM.toString() + "应付:" +contextPlatinum.count(pay));


        Strategy strategyDuamond = StrategyFactory.getInstance(CustomerType.DUAMOND);
        Context contextDuamond  = new Context(strategyDuamond);
        System.out.println(CustomerType.DUAMOND.toString() + "应付:"+contextDuamond.count(pay));

    }

结果:

CustomerType{index=0, message='普通用户'}应付:100.0
CustomerType{index=1, message='白金用户'}应付:98.0
CustomerType{index=2, message='钻石用户'}应付:90.0

这样的话,以后如果还要加别的会员类型,直接在枚举兑现各种增加类型,然后实现策略接口,在策略工厂中稍作修改就可以实现功能,不用去修改业务主体代码,减少了if else 的判断。

 

四、优化

    每增加一个用户类型后,还是需要去修改策略工厂类,我在想有没有办法去根据客户端的类型,动态加载子类策略的方法。

    后来看到有网友通过使用反射以及注解的方式实现了动态加载,根据这个思路继续做一个调整。

   

//客户端类型注解
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
public @interface CustomerTypeAnnotation { CustomerType customerType() default CustomerType.NORMAL; }

 

 

未完待续=======

 

 

 

部分参考 : https://www.cnblogs.com/zdd-java/p/6143935.html 

转载于:https://www.cnblogs.com/zhazhahui/p/11109126.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值