还在用繁琐的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()
    }
}


相关文章
|
7月前
|
设计模式 算法 前端开发
【面试题】什么是策略模式?用了策略模式之后,再也不用写那么多 if else 了,真香!
【面试题】什么是策略模式?用了策略模式之后,再也不用写那么多 if else 了,真香!
107 0
|
4月前
|
测试技术 Python
解锁Python魔法!装饰器:让你的代码翩翩起舞,简化繁琐逻辑,让编程成为一场戏剧性的华丽变身!
【8月更文挑战第21天】在Python编程中,当需要为函数添加如日志记录、性能测试等功能时,手动重复编写相同代码既冗长又难维护。装饰器提供了解决方案:它是一种特殊函数,包裹目标函数以添加额外功能,而不改变原函数结构。装饰器增强了代码复用性、解耦及灵活性。例如,可通过装饰器轻松记录函数执行时间。更高级用法包括带参数的装饰器、多层装饰器以及使用类作为装饰器。掌握装饰器能显著提升Python代码的质量和效率。
53 5
|
前端开发
前端学习笔记202305学习笔记第二十三天-重构报错解决
前端学习笔记202305学习笔记第二十三天-重构报错解决
51 0
|
Oracle Java 关系型数据库
想要造轮子,你知道反射机制吗?
平时写代码的过程中,我们使用不同的工具框架来提升开发效率,除了基础框架之外,我们自己也想造轮子,封装各种业务平台功能; 一旦需造轮子的时候,那么就需要使用Java造轮子利器:反射; 一些项目中常见的反射应用场景: • 泛化调用: 提前不知道目标RPC的接口和方法,而是开发在后台输入值,根据输入的配置动态请求。 这也是提升效率的一部分,因为不可能所以得RPC接口都要亲自对接的,总要有一部分可以灵活的调用不同接口。
60 0
|
7月前
|
前端开发 测试技术
代码注释怎么写:让你的代码更易维护
在编程中,有一种无声的艺术,那就是代码注释。这可能看起来微不足道,但其实非常关键。它不仅有助于他人理解你的代码,也是自我表达的一种方式。
|
IDE NoSQL Java
我来告诉你代码重构有什么好处
根据两本关于重构的书籍的作者 Martin Fowler的说法 “重构是改变软件系统的过程,它不会改变代码的外部行为,但会改善其内部结构。这是一种清理代码的严格方法,可以最大限度地减少引入错误的机会。本质上,当你重构时,你是在改进编写代码后的设计。”
257 0
|
XML Java 数据格式
你写的代码扩展性高吗?快试试用Spring注入方式来解耦代码!
你写的代码扩展性高吗?快试试用Spring注入方式来解耦代码!
你写的代码扩展性高吗?快试试用Spring注入方式来解耦代码!
|
设计模式 算法 Java
代码复用神器,模板模式实操分享(下)
模板模式,顾名思义,定义一个模板,将部分逻辑以具体方法或者具体构造函数的形式实现,在抽象类中声明一些抽象方法来迫使子类实现剩余的逻辑。 不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板方法模式的用意。
代码复用神器,模板模式实操分享(下)
|
数据安全/隐私保护
单一职责原则-敲代码你不能只自己爽,大家爽才是真的爽
单一职责原则-敲代码你不能只自己爽,大家爽才是真的爽
117 0
单一职责原则-敲代码你不能只自己爽,大家爽才是真的爽
|
存储 前端开发 Java
单元测试难?来试试这些套路
阿里妹导读:测试不应该是一门很高大尚的技术,应该是我们技术人的基本功。但现在好像慢慢地,单元测试已经脱离了基本功的范畴。笔者曾经在不同团队中推过单元测试,要求过覆盖率,但发现实施下去很难。后来在不停地刻意练习后,发现阻碍写UT的只是笔者的心魔,并不是时间和项目的问题。在经过一些项目的实践后,也是有了一些自己的理解和实践,希望和大家分享一下,和大家探讨下如何克服“单元测试”的心魔。
727 0
单元测试难?来试试这些套路