设计模式(三)策略模式的几种实现方式

1,167 阅读3分钟

前言

日常开发过程中,我们写业务代码写的最多的可能就是if…else、else…if,有的时候我们确实要写,但是可以在能不写的时候尽量避免去写它,从而提升自己写代码的优雅性,记得还早以前,那时候我才刚做开发看一些别人写的代码,通常觉得实现一个逻辑为何如此复杂,要加好几个类什么handler、Strategy才能实现,不如一个if else 直接实现逻辑,现在想想当时确实年轻。

基本策略模式

通过定义通用的Strategy接口,不同的业务类实现Strategy,重写自己的业务逻辑,然后通过Context环境类去判断具体走哪个策略方法,虽然解决的通过type去做判断,解决if..else和代码的耦合度,但是依旧显得十分笨重。

Strategy接口

public interface Strategy {

    //保费计算基本方法
    Double premiumFormula(Double cost);

}

策略类

//孩子费用计算
public class ChildrenStrategy implements Strategy { @Override public Double premiumFormula(Double cost) { 
//子女费用减半 
cost =cost*0.5; return cost; } }
//父母费用计算
public class ParentStrategy implements Strategy{ @Override public Double premiumFormula(Double cost) {
//父母八折 
cost =cost*0.8; return cost; } }

环境类

public class Context { private Strategy strategy; public Content(String type) { if (type==“children”){ this.strategy=new ChildrenStrategy(); } if (type==“parent”){ this.strategy = new ParentStrategy(); } } 
//环境类方法计算方法 
public Double contextMethod(Double cost){ return strategy.premiumFormula(cost); } }

测试方法

public class StrategyTest { public static void main(String[] args) { System./out/.println(“子女保费计算金额:”+new 
Content(“children”).contextMethod(100.0)); 
System./out/.println(“父母保费计算金额:”+new Content(“parent”).contextMethod(100.0)); } }

枚举策略模式

通过在枚举类里定义公共抽象方法,不同的枚举策略重写公共抽象方法时间不同业务逻辑

StrategyEnum策略枚举类

public enum StrategyEnum {


    ChildrenStrategy {
        @Override
        public Double premiumFormula(Double cost) {
            cost =cost*0.5;
            return cost;
        }
    },
    ParentStrategy {
        @Override
        public Double premiumFormula(Double cost) {
            cost =cost*0.8;
            return cost;
        }
    };
    //计算方法
    public abstract Double premiumFormula(Double cost);
}

测试方法

由此可见,枚举策略的方式更加轻便,可以不同创建环境类来承担调用的介质,直接通过一个枚举策略类即可实现不同的业务逻辑,只需要传入不同的枚举类型。

public static void main(String[] args) {


    StrategyEnum strategyEnum =StrategyEnum.valueOf(StrategyEnum.ChildrenStrategy.name());
    Double aDouble = strategyEnum.premiumFormula(new Double(2.0));
    System.out.println("孩子金额计算结果:"+new BigDecimal(aDouble));
}

工厂策略模式

业务类实现策略接口,通过@Service注解将此类交给Spring Factory来管理进行初始化,类名作为key,会将策略类放到一个map集合里面。

@Service("ParentStrategy")
public class ParentStrategy implements Strategy{

    @Override
    public Double premiumFormula(Double cost) {
        cost =cost*0.8;
        return cost;
    }
}

业务servcie通过调用已经在Spring IOC容器进行初始化后的策略bean,进行业务逻辑实现。

@Service
public class ExcuteService {

    @Resource
    private Map<String, Strategy> strategyMap;


    public BigDecimal getCalculateAmount(String type) throws IllegalAccessException {

        if (!strategyMap.containsKey(type)){
            throw new IllegalAccessException("type 不存在");
        }

        Strategy strategy = strategyMap.get(type);
        Double aDouble = strategy.premiumFormula(new Double(2.0));

        return new BigDecimal(aDouble);

    }
}

三种策略模式总结

  • 基本策略模式:虽说能实现代替if…else,根据策略类实现不一样的业务逻辑,但是整体策略模式显的非常笨重,不是很灵活,已经不推荐使用这种设计模式开发了。
  • 枚举策略模式:简单轻便,对于简单的策略业务逻辑,非常推荐使用,如有业务逻辑变动只需要更改枚举类即可。
  • 工厂策略模式:适用于相对比较复杂的业务场景,通过工厂模式加载策略类,更加适合在Spring体系下进行开发,易拓展、更加灵活。

最后啰嗦一下,设计模式是帮助我们在写代码的时候,让代码在解耦、灵活、可扩展、删繁就简的基础上,让代码的实现更加优雅,切勿为了单纯使用设计模式而画蛇添足。