这样写代码太优雅了吧

文章目录

      • 优化案例
      • 初次优化
      • 再次优化
      • 看看Spring源码的处理

优化案例

假设一个场景,

开发代码时,需要对类中的方法进行遍历判断有没有注解@NotNull,暂时没有合适的工具类,需要自己手搓一个。


无须多想,分分钟秒了,我们写出如下的代码很简单,妥妥的满足需求。

    public Boolean hashAnnotation(Class<?> clazz) {
        //为了案例,此处不使用clazz.isAnnotationPresent(annotationClass)
        for (Annotation annotation : clazz.getAnnotations()) {
            if (annotation.annotationType().equals(NotNull.class)) {
                return true;
            }
        }
        return false;
    }

然而,事情不会那么简单,后续发现,还需要判断有没有@NotBlank注解。
这会儿不能再傻傻的单写个判断@NotBlank的方法,于是写下的方法支持所有注解的判断,看上去代码有着那么点拓展性。
在这里插入图片描述

    public Boolean hashAnnotation(Class<?> clazz, Class<? extends Annotation> annotationClass) {
        //为了案例,此处不使用clazz.isAnnotationPresent(annotationClass)
        for (Annotation annotation : clazz.getAnnotations()) {
            if (annotation.annotationType().equals(annotationClass)) {
                return true;
            }
        }
        return false;
    }

没有什么代码能一蹴而就,意外不期而遇,开发过程中又需要获取类中的所有只有一个参数的方法,和之前获取注解的方法也没法进行复用,只能重新再写一个了。

    public List<Method> isMethodWithSingleParameterOfType(Class<?> clazz) {
        List<Method> methods = new ArrayList<>();
        for (Method method : clazz.getMethods()) {
            if (method.getParameterCount() == 1) {
                methods.add(method);
            }
        }
        return methods;
    }

初次优化

假如后面开发中,还需要对类内部的方法进行处理,难道每次都要依葫芦画瓢写一个新方法吗?
且不说代码的量在不断膨胀,我们经常挂在口上的可拓展性也几乎没有,后续任何的变动,都有可能影响原有的逻辑,除非无脑写新方法。

作为一个合格的Coder,我们要努力的消灭代码中的坏味道。

简单分析上面的几个案例,寻找其中的共性,分离出其中可变化的部分。

需求都需要遍历类中的所有方法

可变的无非是对方法的操作,比如判断方法注解、获取方法的参数等

依据设计原则,封装不变部分拓展可变部分;
不变的部分撑起函数的骨架,再抽象可变部分,稍微一变动,写出如下的代码。增加接口MethodCallback

    public void doWithMethods(Class<?> clazz, MethodCallback mc) {
        Method[] methods = clazz.getMethods();
        /**
         * 封装不变
         */
        for (Method method : methods) {
            mc.doWith(method);
        }
    }

    /**
     * 抽象可变部分
     */
    @FunctionalInterface
    public interface MethodCallback{

        void doWith(Method method);
    }

将可变的方法操作,封装为接口,一者大大提高了方法的复用性,二者是抽象了操作之后对函数的操作也解耦了,不得不说很优雅。

这样优化之后,我们上述的案例都可以改写如下(只是简单展示,并不完善),如果后续有别的个性化的类似需求,只需稳坐钓鱼台,以不变应万变。

再次优化

如果上述案例中再多一个可变的部分,比如说遍历所有方法名称为XXX的注解,
怎么办呢?

依据前面的设计,再次抽象,将过滤再次独立隔离,当做可变部分,增加接口MethodFilter

方法骨架内增加固定逻辑,在方法执行之前,先过滤下方法matches(),支持调用方使用任何的过滤逻辑。


    public void doWithMethods(Class<?> clazz, MethodCallback mc, MethodFilter mf) {
        Method[] methods = clazz.getMethods();
        /**
         * 封装不变
         */
        for (Method method : methods) {
            if (!mf.matches(method)) {
                continue;
            }
            mc.doWith(method);
        }
    }

    /**
     * 抽象可变部分
     */
    @FunctionalInterface
    public interface MethodFilter {

        boolean matches(Method method);
    }

看看Spring源码的处理

ReflectionUtils

package org.springframework.util  #ReflectionUtils

骨架方法
在这里插入图片描述

抽象的接口方法
在这里插入图片描述


上述案例即来自Spring的这个代码类,让我觉得尤其惊艳的点,就是对方法行为的封装,MethodCallbackMethodFilter

许多优秀设计中抽象不单单针对是对具象实体,像这种对无法被归成某一类的抽象,让代码更优雅,更值得反复揣摩。
在这里插入图片描述

正如【HeadFirst 设计模式】开篇中的,【组合优先于继承】章节,对duck实体的飞行方式,鸣叫属性的抽象,有异曲同工之妙。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/662653.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CSS学习笔记:响应式布局的原理——媒体查询

什么是响应式布局&#xff1f; 在实际书写代码时&#xff0c;我们不会自己去手写媒体查询来实现响应式布局&#xff0c;我们一般会调用现成的代码库或使用现成的框架&#xff08;但这些代码库或框架的底层原理是媒体查询&#xff0c;所以了解媒体查询也是很有必要的&#xff0…

应用弹窗优先级

背景 由于活动业务越来越多&#xff0c;积累的弹窗越来越多和杂乱&#xff0c;出现如下弹窗交互问题&#xff1a; 弹窗无限重叠&#xff0c;影响操作 弹出顺序无优先级&#xff0c;重要弹窗被隐藏 原因相信大家都一样&#xff0c;产品是一次次迭代的&#xff0c;也可能是不…

ozon卖家精灵,ozon卖家怎么使用

在跨境电商的浪潮中&#xff0c;OZON作为俄罗斯领先的电商平台&#xff0c;吸引了众多卖家争相入驻。然而&#xff0c;面对日益激烈的市场竞争&#xff0c;如何提升店铺的运营效果&#xff0c;成为卖家们迫切需要解决的问题。而OZON卖家精灵作为一款专为OZON卖家打造的辅助工具…

Lua的几个特殊用法

&#xff1a;/.的区别 详细可以参考https://zhuanlan.zhihu.com/p/651619116。最重要的不同就是传递默认参数self。 通过.调用函数&#xff0c;传递self实例 通过 &#xff1a; 调用函数&#xff0c;传递self (不需要显示的传递self参数&#xff0c;默认就会传递&#xff0c;但…

ROS | C++和python实现发布结点和订阅结点

发布者结点&#xff1a; 代码实现&#xff1a; python: C: C和Python发布结点的差异&#xff1a; python: 发布结点pub 大管家rospy调用publisher函数发布话题 (话题,类型&#xff0c;话题长度&#xff09; C: 先定义一个大管家&#xff1a;NodeHandle 然后大管家发布话题…

【C++】二维前缀和

1.题目 2.算法思路 和一维前缀和的方法类似&#xff0c;我们需要预处理一个求和矩阵&#xff0c;然后再求和。 下面是模板&#xff1a; 上面两张图片总结出来了两个公式&#xff0c;这是解决此类问题的关键。 3.代码 #include <iostream> using namespace std; #incl…

【车载开发系列】Vector工具链的安装

【车载开发系列】Vector工具链的安装 【车载开发系列】Vector工具链的安装 【车载开发系列】Vector工具链的安装一. VectorDriver二. DaVinci_Developer三. DaVinci Configurator 一. VectorDriver Vector Driver Setup是Vector产品链中重要的驱动软件,所有的硬件设备进行连接…

看看最新的B端登录界面,你是不是被潮流抛弃了?

毛玻璃风格&#xff08;Frosted Glass Style&#xff09;是新拟态设计风格中的一种分支&#xff0c;它灵感来源于现实世界中的毛玻璃材质。毛玻璃是一种通过在玻璃表面加工处理的方式&#xff0c;使其具有模糊、云翳和透明效果的特殊玻璃。 在设计中&#xff0c;毛玻璃风格通常…

PS:电子书App自动截图后合成一个PDF文档

说明&#xff1a;有的电子书App不能下载到本地&#xff0c;通过自动截图后合成一个PDF文档来解决&#xff01; 一、自动截图App 1.安装”免ROOT自动化助手“ 2.创建一个任务 3.编辑任务&#xff1a;根据电子书的操作顺序制定&#xff0c;400次就是书籍页数&#xff08;次数一…

备份服务器的安全风险以及如何通过TDE透明加密提升安全性

备份服务器的潜在安全风险主要包括以下几个方面&#xff1a; 1. 数据泄露风险&#xff1a; 备份数据可能包含敏感信息&#xff0c;如用户个人信息、商业机密等。如果备份数据未经适当保护&#xff0c;例如存储在不安全的位置或未加密&#xff0c;黑客或未授权的人员可能会获取…

React-基础样式控制

组件基础样式方案 React组件基础的样式控制有两种方式 1、行内样式&#xff08;不推荐&#xff09; 属性名是多个单词的需要使用驼峰写法 也可以把样式都提取到一个变量里&#xff0c;再赋值到style里 2、class类名控制 classnames优化类名控制 classnames是一个简单的JS库&…

【揭秘!在线ChatGPT神器,体验入口在此!】

&#x1f680;【揭秘&#xff01;在线ChatGPT神器&#xff0c;体验入口在此&#xff01;】&#x1f680; 前言 嘿&#xff0c;大家好&#xff01;今天我要和大家分享一些关于如何使用免费的ChatGPT的技巧。ChatGPT是一项令人兴奋的人工智能技术&#xff0c;它可以成为我们的好…

沃飞长空总部落地成都高新,为蓉低空经济发展助力!

5月25日&#xff0c;吉利科技集团与成都高新区签署合作协议&#xff0c;吉利科技集团旗下沃飞长空全球总部落地成都高新区。 根据协议&#xff0c;沃飞长空全球总部项目落地成都未来科技城&#xff0c;将布局总部办公、研发和生产制造低空出行航空器等业务。双方将积极发挥各自…

MySQL第六次作业

一、创建部门表 指令&#xff1a; mysql> CREATE TABLE dept (-> dept_id INT PRIMARY KEY AUTO_INCREMENT COMMENT 部门编号,-> dept_name CHAR(20) COMMENT 部门名称-> ); 演示&#xff1a; 二、插入部门数据 指令&#xff1a; mysql> INSERT INTO dept…

如何使用GPT-4o?如何使用 GPT-4o API?

如何使用GPT-4o&#xff1f; GPT-4o 也可以通过 ChatGPT 界面使用 如何使用 GPT-4o API 新的 GPT-4o 模型遵循 OpenAI 现有的聊天完成 API&#xff0c;使其向后兼容且易于使用。 ​ 如何升级GPT4Plus&#xff1f; 升级ChatGPTPLSU4需要一张虚拟卡&#xff0c;点击获取​​​…

vue项目集成萤石云在Web系统中实现实时摄像头监控及控制功能

需求 需求&#xff1a; 开发人员在产线上放置一个萤石摄像头&#xff0c;前端在可视化大屏上实时监控&#xff0c;且控制左右上下功能。 效果 萤石云接入web前期准备工作 阅读萤石云API文档&#xff1a;萤石云开放平台开发者文档 阅读萤石云控制API文档&#xff1a;萤石云摄…

企业电脑加密系统是如何发展的,今天最可靠的电脑加密系统是什么

企业电脑加密系统历经了几十年的发展&#xff0c;如今技术已经逐渐成熟&#xff0c;加密强度和防泄密效果越来越显著&#xff0c;那么它是怎么发展的&#xff0c;以及当今使用的加密技术是什么呢&#xff1f; 一、发展历程 1.早期探索阶段&#xff1a; 时间&#xff1a;上世纪…

SELINUX=enforcing时无法启动httpd服务的解决方案(semanage命令以及setroubleshoot-server插件的妙用)

一、问题描述&#xff1a; 当/etc/selinux/conf被要求必须是SELINUXenforcing&#xff0c;不被允许使用setenforce 0宽松模式 我们启动httpd就会报错&#xff1a; Job for httpd.service failed because the control process exited with error code. See "systemctl s…

在outlook的邮件中插入HTML;HTML模板获取;页面组态手动生成HTML

本文介绍如何在outlook发送邮件时&#xff0c;在邮件中插入HTML&#xff0c;此HTML可以从获取模板自行进行修改。 文章目录 一、下载HTML模板&#xff08;或自己制作好HTML文件&#xff09;二、outlook新增宏三、新建邮件&#xff0c;插入HTML四、通过图像化页面组态手动生成HT…

sprongboot+vue 游泳馆管理系统

游泳馆管理系统 spring bootvue 主要有游泳课程预约、网上购票、教练预约、游泳器材管理、会员管理等功能&#xff1b; 1、管理员 登录、修改密码 购票管理&#xff1a;查看订单、删除订单、修改订单 教练管理&#xff1a;教练信息查询、修改 课程信息&#xff1a;增删改查课程…