策略模式

问题

场景

根据不同的会员等级,返回不同的打折优惠券

if else解决

在没有用设计模式时,会出现如下多重if else的代码

if(type=="白银"){
  doBySomething();
}else if(type=="黄金"){
  doHjSomething();
}else if(type=="钻石"){
  doZsSomething();
}
....

使用策略模式+枚举

    /**
     * 只需要一行代码
     * @param type
     */
    public static void doWithStrategy(BusinessesType type) {
        StrateFactory.getInstance().getStrategy(type).process();
    }

实现

策略模式通用类图

代码实现

定义接口

package com.tmq.learn.strategy;
/**
 * @author tangmqb
 * @version 1.0.0
 * 2022/3/23
 * 策略模式
 * 需求
 * 根据不同的会员等级返回不同金额的优惠券
 */
public interface Istrategy {
    int process();
    String getType();
}

枚举定义会员类别

package com.tmq.learn.strategy;

/**
 * @author tangmqb
 * @version 1.0.0
 * 2022/3/23
 */
public enum BusinessesType {

    BAI_YIN(1,"白银会员"),
    HUANG_JIN(2,"黄金会员"),
    ZHUAN_SHI(3,"钻石会员");
    
    private int level;
    private String name;

    BusinessesType(int level, String name) {
        this.level = level;
        this.name = name;
    }

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

定义会员获取优惠券规则

白银

package com.tmq.learn.strategy;

/**
 * @author tangmqb
 * @version 1.0.0
 * 2022/3/23
 */
public class BaiJinStrategy implements Istrategy{
    @Override
    public int process() {
        System.out.println("我是"+getType()+",我能打9折");
        return 9;
    }

    @Override
    public String getType() {
        return BusinessesType.BAI_YIN.getName();
    }
}

黄金

package com.tmq.learn.strategy;

/**
 * @author tangmqb
 * @version 1.0.0
 * 2022/3/23
 */
public class HuangJinStrategy implements Istrategy {
    @Override
    public int process() {
        System.out.println("我是"+getType()+",我能打7折");
        return 7;
    }

    @Override
    public String getType() {
        return BusinessesType.HUANG_JIN.getName();
    }
}

钻石

package com.tmq.learn.strategy;

/**
 * @author tangmqb
 * @version 1.0.0
 * 2022/3/23
 */
public class ZhuangShiStrategy implements Istrategy{
    @Override
    public int process() {
        System.out.println("我是"+getType()+",我能打5折");
        return 5;
    }

    @Override
    public String getType() {
        return BusinessesType.ZHUAN_SHI.getName();
    }
}

通过工厂类提供策略

package com.tmq.learn.strategy;

import java.util.HashMap;

/**
 * @author tangmqb
 * @version 1.0.0
 * 2022/3/23
 */
public class StrateFactory {

    private HashMap<BusinessesType,Istrategy> map;
    public StrateFactory() {
        map = new HashMap<>();
        map.put(BusinessesType.BAI_YIN, new BaiJinStrategy());
        map.put(BusinessesType.HUANG_JIN, new HuangJinStrategy());
        map.put(BusinessesType.ZHUAN_SHI, new ZhuangShiStrategy());
    }

    private static class InnerInstance{
        private static StrateFactory INSTANCE = new StrateFactory();
    }

    public static StrateFactory getInstance() {
        return InnerInstance.INSTANCE;
    }

    public Istrategy getStrategy(BusinessesType type) {
        return map.get(type);
    }
}

客户端调用

package com.tmq.learn.strategy;

/**
 * @author tangmqb
 * @version 1.0.0
 * 2022/3/23
 */
public class Client {
    public static void main(String[] args) {
        doWithStrategy(BusinessesType.BAI_YIN);
        doWithStrategy(BusinessesType.HUANG_JIN);
        doWithStrategy(BusinessesType.ZHUAN_SHI);
    }

    /**
     * 只需要一行代码
     * @param type
     */
    public static void doWithStrategy(BusinessesType type) {
        StrateFactory.getInstance().getStrategy(type).process();
    }
    /**
     * 不使用策略模式时的实现
     * 多重if判断
     * 耦合度太高
     * 扩展麻烦
     * @param type
     */
    public static void doWithoutStrategy(BusinessesType type) {
        if (type == BusinessesType.BAI_YIN) {
            new BaiJinStrategy().process();
        } else if (type == BusinessesType.HUANG_JIN) {
            new HuangJinStrategy().process();
        } else if (type == BusinessesType.ZHUAN_SHI) {
            new ZhuangShiStrategy().process();
        }
    }
}

执行结果

我是白银会员,我能打9折
我是黄金会员,我能打7折
我是钻石会员,我能打5折
Process finished with exit code 0

总结

策略模式优点

● 算法可以自由切换

这是策略模式本身定义的,只要实现抽象策略,它就成为策略家族的一个成员,通过封 装角色对其进行封装,保证对外提供“可自由切换”的策略。

● 避免使用多重条件判断

如果没有策略模式,我们想想看会是什么样子?一个策略家族有5个策略算法,一会要 使用A策略,一会要使用B策略,怎么设计呢?使用多重的条件语句?多重条件语句不易维 护,而且出错的概率大大增强。使用策略模式后,可以由其他模块决定采用何种策略,策略 家族对外提供的访问接口就是封装类,简化了操作,同时避免了条件语句判断。

● 扩展性良好

这甚至都不用说是它的优点,因为它太明显了。在现有的系统中增加一个策略太容易 了,只要实现接口就可以了,其他都不用修改,类似于一个可反复拆卸的插件,这大大地符 合了OCP原则。

策略模式缺点

● 策略类数量增多

每一个策略都是一个类,复用的可能性很小,类数量增多。

● 所有的策略类都需要对外暴露

end
  • 作者:tmq(联系作者)
  • 发表时间:2022-03-23 17:05
  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 转载声明:如果是转载栈主转载的文章,请附上原文链接
  • 公众号转载:请在文末添加作者公众号二维码(公众号二维码见右边,欢迎关注)
  • 评论