问题
场景
根据不同的会员等级,返回不同的打折优惠券
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原则。
策略模式缺点
● 策略类数量增多
每一个策略都是一个类,复用的可能性很小,类数量增多。
● 所有的策略类都需要对外暴露
评论