还在用繁琐的if..else,试试策略模式吧!

简介: 应该有不少码友遇到过充斥着if else的代码,面对这样的一团乱麻,简单粗暴地继续增量修改常常只会让复杂度越来越高,可读性越来越差。那么是时候重构了,花几分钟看看这篇文章, 说不定对你有一丢丢帮助。

前言

应该有不少码友遇到过充斥着if else的代码,面对这样的一团乱麻,简单粗暴地继续增量修改常常只会让复杂度越来越高,可读性越来越差。那么是时候重构了,花几分钟看看这篇文章, 说不定对你有一丢丢帮助。

业务场景

有这么一个小需求,需要对不同类型的用户进行不同规则的操作,场景大概如下所示:

if (普通用户) {
 // 此处省略...
}
if (会员用户) {
  // 此处省略...
}
if (钻石用户) {
  // 此处省略...
}
复制代码

按照上述的条件我们可以得出的结论是:

根据现在的流程来看,如果有一个不匹配的话,其实后续的流程是不用执行的,就是需要具备一个短路的功能。对于目前的现状来说,如果在原有的基础上来改,只要稍微注意一下解决现在的需求不是很大的问题,但是后面可维护性非常差。

策略模式

策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。

策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面,作为一个抽象策略类的子类。用一句话来说,就是:“准备一组算法,并将每一个算法封装起来,使得它们可以互换”。

这个模式涉及到三个角色:

  • 环境(Context)角色:持有一个Strategy的引用。
  • 抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
  • 具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

优化方案

使用普通的策略模式进行优化。

1.定义接口:

public interface Type {
    /**
     * 获取类型,返回集合
     */
    Bollean userRule();
}
复制代码

2.定义 UserType(普通)实现 Type 接口:

@Service
public class UserType implements Type {
    @Override
    public Bollean userRule() {
        // 此处省略普通用户的规则操作...
        return true;
    }
}
复制代码

3.定义 VIPUserType(vip用户)实现 Type 接口:

@Service
public class VIPUserType implements Type {
    @Override
    public Bollean userRule() {
        // 此处省略普通用户的规则操作...
        return true;
    }
}
复制代码

4.定义策略工厂类:

public class TypeFactory {
    private static TypeFactory typeFactory = new TypeFactory();
    // 定义Map
    private static Map<Integer,Type> map = new HashMap<>();
    static{
        map.put(1, new UserType());
        map.put(2, new VIPUserType())
    }
    public static TypeFactory getInstance(){
        return typeFactory;
    }
    public Type getByType(Integer type){
        return map.get(type);
    }
}
复制代码

5.使用

TypeFactory.getInstance().getByType(1).userRule();
复制代码

问题

在上面策略模式中如果在实现类 UserType 中使用

@Autowired
private Dao dao;
复制代码

就会出现 空指针的情况

java.lang.NullPointerException
复制代码

因为 发现策略实现中的Dao接口注入的都是Null。

改造

@Service("userType")
public class UserType implements Type {
    @Autowired
    private Dao dao;
    @Override
    public Bollean userRule() {
        // 此处省略普通用户的规则操作...
        return true;
    }
}
复制代码
@Service("vIPUserType")
public class VIPUserType implements Type {
    @Autowired
    private Dao dao;
    @Override
    public Bollean userRule() {
        // 此处省略普通用户的规则操作...
        return true;
    }
}
复制代码
public class TypeFactory {
    @Resource
    @Qualifier("userType")
    private  UserType userType;
    @Resource
    @Qualifier("vIPUserType")
    private  VIPUserType vIPUserType;
    public  Type getByType(Integer type){
        Map<Integer, Type> map = new HashMap<>();
        map.put(1, userType);
        map.put(2, vIPUserType);
        return map.get(type);
    }
}
复制代码
public class Test {
    // 工厂注入
    @Autowired
    private TypeFactory typeFactory;
    @GetMapper("/test")
    public void test(Integer type) {
        typeFactory.getByType(type).getType()
    }
}


相关文章
|
9月前
|
设计模式 算法 前端开发
【面试题】什么是策略模式?用了策略模式之后,再也不用写那么多 if else 了,真香!
【面试题】什么是策略模式?用了策略模式之后,再也不用写那么多 if else 了,真香!
119 0
|
6月前
|
设计模式 缓存 算法
揭秘策略模式:如何用Java设计模式轻松切换算法?
【8月更文挑战第30天】设计模式是解决软件开发中特定问题的可重用方案。其中,策略模式是一种常用的行为型模式,允许在运行时选择算法行为。它通过定义一系列可互换的算法来封装具体的实现,使算法的变化与客户端分离。例如,在电商系统中,可以通过定义 `DiscountStrategy` 接口和多种折扣策略类(如 `FidelityDiscount`、`BulkDiscount` 和 `NoDiscount`),在运行时动态切换不同的折扣逻辑。这样,`ShoppingCart` 类无需关心具体折扣计算细节,只需设置不同的策略即可实现灵活的价格计算,符合开闭原则并提高代码的可维护性和扩展性。
83 2
|
Oracle Java 关系型数据库
想要造轮子,你知道反射机制吗?
平时写代码的过程中,我们使用不同的工具框架来提升开发效率,除了基础框架之外,我们自己也想造轮子,封装各种业务平台功能; 一旦需造轮子的时候,那么就需要使用Java造轮子利器:反射; 一些项目中常见的反射应用场景: • 泛化调用: 提前不知道目标RPC的接口和方法,而是开发在后台输入值,根据输入的配置动态请求。 这也是提升效率的一部分,因为不可能所以得RPC接口都要亲自对接的,总要有一部分可以灵活的调用不同接口。
68 0
|
9月前
|
前端开发 测试技术
代码注释怎么写:让你的代码更易维护
在编程中,有一种无声的艺术,那就是代码注释。这可能看起来微不足道,但其实非常关键。它不仅有助于他人理解你的代码,也是自我表达的一种方式。
|
运维 监控 Shell
太牛了!100个Shell脚本实例,代码清晰拿来就能用,再也不怕写不对了!
太牛了!100个Shell脚本实例,代码清晰拿来就能用,再也不怕写不对了!
|
IDE NoSQL Java
我来告诉你代码重构有什么好处
根据两本关于重构的书籍的作者 Martin Fowler的说法 “重构是改变软件系统的过程,它不会改变代码的外部行为,但会改善其内部结构。这是一种清理代码的严格方法,可以最大限度地减少引入错误的机会。本质上,当你重构时,你是在改进编写代码后的设计。”
264 0
|
编解码 前端开发 程序员
为啥只跟着视频敲代码学不好编程?
为啥只跟着视频敲代码学不好编程?
495 1
|
XML Java 数据格式
你写的代码扩展性高吗?快试试用Spring注入方式来解耦代码!
你写的代码扩展性高吗?快试试用Spring注入方式来解耦代码!
你写的代码扩展性高吗?快试试用Spring注入方式来解耦代码!
|
设计模式 算法 Java
代码复用神器,模板模式实操分享(下)
模板模式,顾名思义,定义一个模板,将部分逻辑以具体方法或者具体构造函数的形式实现,在抽象类中声明一些抽象方法来迫使子类实现剩余的逻辑。 不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板方法模式的用意。
代码复用神器,模板模式实操分享(下)
|
设计模式 存储 算法
再一次实战策略模式,真是太好用了
再一次实战策略模式,真是太好用了
167 0
再一次实战策略模式,真是太好用了