看了架构师的代码,切身感受到了代码可扩展性高的魅力

ANSYS ICEM CFD 2023R2 结构化网格实战:翼型绕流 10 步生成高质量六面体网格 在计算流体力学(CFD)分析中,网格质量直接决定了仿真结果的精度和收敛性。对于翼型绕流这类典型的外部流动问题,结构化网格因其规则的节点排列和优异的边界层捕捉能力,成为高精度模拟的首选方案。通过在后缘处添加局部H型拓扑,并将过渡区增长率降至1.1,最终使网格质量指标提升40%,计算收敛速度提高2倍。这印证了结构化网格在复杂流动模拟中的不可替代性——虽然初期投入时间较多,但能显著提升计算精度和稳定性。在开始网格划分前,合理的几何准备是确保后续流程顺利的关键。对于翼型绕流,O型网格拓扑能提供最佳的边界层适应性。 阅读详情

前言

开发有个著名的设计原则:开闭原则,即对扩展开放,对修改关闭。但是实际开发中鲜有人能运用纯熟,少侠在开发中接触的例子就是,大多数人就是if…else…这样难以扩展的条件判断。那么应该如何优雅的精简掉复杂的逻辑判断呢?当然抽象共性是从产品思维角度的优化方案,今天少侠想说的是通过技术手段实现。

业务背景

首先简单介绍一下业务背景,背景很简单,就是有若干渠道源,如阿里巴巴,腾讯等,针对不同的渠道需要有不同的数据处理逻辑,并且渠道来源之后会不断扩展。

初步实现

先建立一个简单的枚举类:

/**
 * @author Carson
 * @date 2020/8/24 下午3:10
 */
public enum SourceEnum {
    /**
     * 阿里巴巴
     */
    ALIBABA("ALIBABA"),
    /**
     * 腾讯
     */
    TENCENT("TENCENT"),
    ;
    public String name;
    SourceEnum(String name) {
        this.name = name;
    }
    //匹配
    public static SourceEnum match(String name){
        SourceEnum[] values = SourceEnum.values();
        for (SourceEnum value : values) {
            if(value.name.equals(name)){
                return value;
            }
        }
        return null;
    }
    public String getName() {
        return name;
    }
}
复制代码

再来看看业务层接口和具体的实现类(注意实现类上的@Service注解是指定的了别名的,方便之后利用 @Qualifier注解调用):

/**
 * @author Carson
 * @date 2020/8/24 下午3:10
 */
public interface DataService {
    String dataProcess();
}
/**
 * @author Carson
 * @date 2020/8/24 下午3:14
 */
@Service("alibabaServiceImpl")
public class AlibabaServiceImpl implements DataService {
    @Override
    public String dataProcess() {
        return "Alibaba Process++++++++++++++";
    }
}

/**
 * @author Carson
 * @date 2020/8/24 下午3:12
 */
@Service("tencentServiceImpl")
public class TencentServiceImpl implements DataService {
    @Override
    public String dataProcess() {
        return "Tencent Process++++++++++++++";
    }
}
复制代码

再来看看接口层的实现,主要是让用户传入渠道源source(真实环境中这个可能是从cookies里的用户信息获取,这里且不讨论),然后根据不同的渠道进行判断,注意看代码里的switch…case…语句,如果之后渠道扩展了,这里势必是要做改动的。有人可能觉得,看着还阔以啊,干净整洁,但是之后要是渠道很多呢,万一百八十个渠道,这里看着就很臃肿,并且万一出错排查起来也不方便,说得专业一点,就是扩展性不好。

/**
 * @author Carson
 * @date 20-8-20 下午5:00
 */
@RestController
public class CommonController {
    private final Logger logger = LoggerFactory.getLogger(CommonController.class);
    @Qualifier(value = "alibabaServiceImpl")
    @Autowired
    private AlibabaServiceImpl alibabaServiceImpl;
    @Qualifier(value = "tencentServiceImpl")
    @Autowired
    private TencentServiceImpl tencentServiceImpl;
    @GetMapping("/dataHandler")
    public String dataHandler(String source) {
        if (StringUtils.isBlank(source)) {
            return "Empty data";
        }
        SourceEnum sourceEnum = SourceEnum.match(source);
        if (sourceEnum == null) {
            return "Empty data";
        }
        switch (sourceEnum) {
            case ALIBABA:
                return alibabaServiceImpl.dataProcess();
            case TENCENT:
                return tencentServiceImpl.dataProcess();
            default:
                return "Empty data";
        }
    }
}
复制代码

代码优化

优化的第一步是从枚举类开始,为每个枚举类指定对应的Service实现类对象,注意,Spring中接口不能被加载成Bean实例,所以需要为属性和方法添加@Lookup注解)。

@Service
public interface DataService {
    // 注意,此处必须加此@Lookup注解,否则容器无法启动
    @Lookup
    String dataProcess();
}
复制代码
public class AlibabaServiceImpl implements DataService {
    public AlibabaServiceImpl(){}
    @Override
    public String dataProcess() {
        return "Alibaba Process++++++++++++++";
    }
}
public class TencentServiceImpl implements DataService {
    @Override
    public String dataProcess() {
        return "Tencent Process++++++++++++++";
    }
}
复制代码

然后是改进后的枚举类:

/**
 * @author Carson
 * @date 2020/8/24 下午3:10
 */
public enum SourceEnum {
    /**
     * 阿里巴巴
     */
    ALIBABA("ALIBABA", new AlibabaServiceImpl()),
    /**
     * 腾讯
     */
    TENCENT("TENCENT", new TencentServiceImpl()),
    ;
    public String name;
    public DataService dataService;
    SourceEnum(String name, DataService dataService) {
        this.name = name;
        this.dataService = dataService;
    }
    //匹配
    public static SourceEnum match(String name) {
        SourceEnum[] values = SourceEnum.values();
        for (SourceEnum value : values) {
            if (value.name.equals(name)) {
                return value;
            }
        }
        return null;
    }
    public String getName() {
        return name;
    }
    public DataService getDataService() {
        return dataService;
    }
}
复制代码

然后接口层的改造如下,注意看这里的注解只是配置了接口的自动装配(并未注解所有的实现类),然后通过多态实现具体调用。

@RestController
public class CommonController {
    private final Logger logger = LoggerFactory.getLogger(CommonController.class);
    
    @Autowired
    private DataService dataService;
    @GetMapping("/dataHandler")
    public String dataHandler(String source) {
        if (StringUtils.isBlank(source)) {
            return "Empty data";
        }
        SourceEnum sourceEnum = SourceEnum.match(source);
        if (sourceEnum == null) {
            return "Empty data";
        }
        AbstractDataService dataService = sourceEnum.dataService;
        if (dataService == null) {
            return "Empty data";
        }
        return dataService.dataProcess();
    }
}
复制代码

小结

通过使用枚举类,在枚举中将 属性与规则具体实现进行绑定。通过改变可以减少if -else使得代码更加优雅 如果需要新增渠道,我们只需要在编写具体规则实现类时实现DataService接口,并在枚举类中新增的枚举,而不需要改动到原先的任何代码。这符合了开闭原则。
由于Spring默认是单例模式,所以正常开发一个接口有多个实现类都是一个一个指定(@Qualifier)装配,但是如果想利用多态,让程序决定由哪个具体实现类执行,可以将@Service注解配置在接口上,同时为接口属性/方法添加@Lookup注解。

点点关注,不会迷路

 

Q3D提取PCB走线RLCG参数 介绍一种提取PCB走线寄生电容和寄生电感的方法 阅读详情

相关推荐

超详细Tokenizer——文本训练数据预处理

Tokenizer是Keras库中的一个文本处理工具,它用于将文本分词并构建词汇表,同时将文本映射到整数序列。这对于自然语言处理任务非常有用,例如文本分类、情感分析、机器翻译等。

halo的博客 3701

写扩展性好的代码:函数

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34261739的博客 335

Ubuntu安装opencv4.5(自己安装过程详细)

1.下载opencv 在opencv官网下载source版,下载链接 http://opencv.org/releases.html。别下载错版本 下载过程就不多说了。 2.安装过程 2.1解压 unzip opencv-4.5.0.zip cd opencv-4.5.0 2.2安装依赖的库 sudo apt-get install cmake sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-

weixin_45629790的博客 1万+

架构师的道法术:架构师是否需要下场写代码?

架构师是否需要下场写代码,并没有一个简单的“是”或“否”的答案。写代码对于架构师来说是一种能力,它帮助架构师保持技术敏感度,验证设计的可行性,并与开发团队保持紧密联系。但随着架构师职责的不断拓展,编写代码的深度和广度将不再是唯一的衡量标准。架构师的“道”在于深刻理解业务需求,设计出可行的技术架构;“法”在于通过团队协作和技术领导来确保架构的实施;而“术”则是依赖架构师在技术实践中积累的经验。

947

宝马项目化流程标准(BMW ABC flyer requirement)

宝马项目化流程标准(BMW ABC flyer requirement)

于大博 7252

【Codesys】获取从站信息,判断是否从站断联,总线丢失

获取EtherCAT从站信息,判断是否从站断联,总线丢失

qq_35316470的博客 5732

架构师:优秀的代码都是如何分层的?

我还为大家准备了一套体系化的架构师学习资料包以及BAT面试资料,供大家参考及学习已经将知识体系整理好(源码,笔记,PPT,学习视频)《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门即可获取!

2401_84046895的博客 866

安卓设备安全相关技术

当前安卓设备使用的加密方案是基于Soc中一块可写入的rom实现,称为熔丝,其结果不可逆。 1、secureboot 2、AVB(Android Verify Boot) 3、dm-verity(device mapper) 4、keymaster 5、crypto 6、rpmb(replay private memory block) 7、TEE(Trust execute environment) 8、SELinux .........

weixin_43797328的博客 4838

DataProcessorService

public IDataReader GetFunctionInfo(int functionId) { this.PoolConnect(); SqlParameter para = new SqlParameter("@FUNCTION_ID", functionId); return SqlHelper.ExecuteReader(this....

weixin_30426879的博客 151

深入剖析:功率放大电路设计精髓——从理论到实践

输入信号首先被调制(通常是PWM脉宽调制)成高频开关信号,驱动功率开关管(MOSFET),再通过LC低通滤波器滤除高频分量,还原出放大的音频信号。在靠近功放板电源引脚处放置足够容量的电解电容(如100uF - 1000uF)和高频瓷片电容(如0.1uF)并联进行电源去耦,抑制低频和高频干扰,防止低频振荡(Motorboating)和高频自激。,堪称电子世界里的“能量转换器”。当输入信号在零附近(即两个器件切换导通的区域)时,由于器件的开启电压(Vbe或Vgs)不为零,输出波形会出现明显的衔接不流畅的失真。

Zihan2558的博客 1697

Oracle 查看 rman 备份情况 SQL 语句

每天一个 DBA 小知识,助你更进一步!

LuciferLiu_DBA 3119

DataService系列教程 (一)

DataService系列教程 (一) 之前做了一些小项目,用到了DataService这个数据调用框架,所以根据自己实际理解和网上的一些参考,自己做了一些小随笔,方便以后记忆! 关于ADO.NET Entity Framework部分的内容见ADO.NET Entity Framework(1-4) http://kb.cnblogs.com/page/43963/ 本文例子下载:ht...

weixin_30335353的博客 2052

基于遗传算法的码头泊位分配调度优化问题求解

例如,基因型为 [3, 1, 4, 2] 表示第一艘停靠在第三个泊位,第二艘停靠在第一个泊位,以此类推。同时,该码头有 n 艘船需要停靠,每艘船的货物数量、船长、船宽都不同,需要根据其特性来分配合适的泊位,并确定每个泊位的使用时间,以最大化码头的使用效率。码头的泊位分配调度是一个关键的物流问题,它涉及到船舶的进出港、货物的装卸和存储等多个方面,因此对其进行优化是至关重要的。根据得到的最优个体,可以得到每个泊位停靠的船只、使用时间等信息,从而确定码头的泊位分配调度方案。% 不同船只的货物数量。

uote_e的博客 1075

多图详解:七种具体方法增强代码可扩展性

欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章,主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等,同时欢迎大家加我个人微信「java_front」一起交流学习 1 六大原则 在设计模式中有六大设计原则: 单一职责原则:一个类只做一件事 里式替换原则:子类可以扩展父类 依赖倒置原则:面向接口编程 接口隔离原则:高内聚低耦合 迪米特法则:最少知道原则 开闭原则:关闭修改,开放新增 我认为在这六个原则中开闭原则最为重要,开闭原则是可扩展性的重要基石。 第一个原因是需求变化时应该通过新.

JAVA前线技术专栏 3198

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

我是如何提高代码的可扩展性的

最近写了一个逻辑表达式引擎(everlogic),对于如何提高代码的可扩展性做了一些思考,在这里做个总结,希望对大家有所启发。 该引擎想要达到的目标是传入一组参数,判断参数是否满足一定的逻辑条件。如传入参数 A 和 B,判断A、B是否都大于100,且 A 大于 B,逻辑表达式如下 A > 100 and B > 100 and A > B 除支持简单的逻辑表达式,还支持多个表达式的聚合,如 (A > 100 and B > 100 and A > B) and (C &g

Mengxiang's Blog 1405

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

代码质量之可扩展性

  可扩展性的动力——不断变化的用户需求 世界上不变的是变化,软件需求不会变化?不可能!一个系统是否拥抱变化是由它的可维护性和可扩展性决定的,软件环境的变化(可能是业务环境,运行环境)导致软件要进行改动才能满足人们对它的要求,这种系统本身适应变化的能力就是可扩展性。   可扩展性的设计忠告 可扩展性对系统的性能和复杂度都有影响,复杂度很高的项目很难维护,亦很难测试,我比较推崇可预见的...

cantellow 1194

让你的代码有更好的扩展性

      代码有良好的扩展性,这每个开发人员的愿望。可是在无尽的需求改动增加和改动下,还有多少人在时时刻刻坚持。更多的时候是思考不到位或贪一时之快写下很多的if/else或者“硬代码”,为后续的需求修改带来很大的麻烦。      今天就遇到一个这样的例子。一个游戏。前后台各维护这一份用户道具的数据。用户购买道具时,为了减少前后台的交互, 前台会自己去对用户道具数据进行操作,但是每个道具购买后逻辑不一样。之前改一个bug,为了快速修复,后台针对一种道具返回对应数据,但是现在又有对不同道具的新需求。考虑到我们

greatwzz的专栏 4527

重构-改善既有代码设计_实用代码重构,第3部分-可扩展性

重构-改善既有代码设计In part 2 of this series I shared questions that dealt with code refactoring for Readability. In this part we’ll spend some time with another aspect, Extensibility. We’ll take the same pra...

culi4814的博客 537

如何提高代码的扩展性

如何提高代码的扩展性 如何提高代码的扩展性 一、架构的高可用?(不是本文的重点) 二、软件项目的变化(为什么要提高代码的可扩展性(背景)) 软件设计的唯一产出物—代码 面向对象的目的是模块化 三、什么是高内聚、低耦合 1、搞清楚模块是什么 例如:如果模块A直接操作了模块B的数据,这种操作模块与模块之间就为强耦合,甚至可以认为这种情况之下基本算没有分模块!如果A只是通过数据与B模块交互,这种我们称之为弱耦合!微服务独立的模块,方便去维护,或者写单元测试等等…如果木块之间的依赖非常严重,将会非常不易于维护。 四

qq_34871037的博客 1625

架构师重构代码的12条军规

作者 |Raffi Krikorian对于开发者来说,架构设计是软件研发过程中最重要的一环,所谓没有图纸,就建不了房子。在遍地App的互联网时代,架构设计有了一些比较成熟的模式,开发者...

web前端开发 279

不知道怎么提高代码可扩展性?来看看优秀框架源码中的这几种设计模式吧!

为什么要提高代码扩展性 我们写的代码都是为了一定的需求服务的,但是这些需求并不是一成不变的,当需求变更了,如果我们代码的扩展性很好,我们可能只需要简单的添加或者删除模块就行了,如果扩展性不好,可能所有代码都需要重写,那就是一场灾难了,所以提高代码的扩展性是势在必行的。怎样才算有好的扩展性呢?好的扩展性应该具备以下特征: 需求变更时,代码不需要重写。 局部代码的修改不会引起大规模的改动。有时候我们去重构一小块代码,但是发现他跟其他代码都是杂糅在一起的,里面各种耦合,一件事情拆在几个地方做,要想改这一小块必

dennis_jiang的博客 1620

浅谈利用多态,继承和接口来封装代码,提高Java代码的可扩展性

一个人做项目的时候是最爽的, 因为可以肆无忌惮的按照自己的想法去"策马奔腾", 因为往往会优先选择实现成本最低且个人偏好的方式去实现, 简单的说就是, 怎么爽就怎么做.这样的情况,项目在实现时候如果只考虑方便快捷而忽略了关键的需求分析和架构设计, 虽然可能很快就能做出来,但质量不高. 并且一个具有生命期的项目, 它的代码是应该具有相当规范的.这个项目应当是, 即使其他工程师加入项目组中也能较快较容

Alex Tam 的专栏 6717

多种负载均衡算法及其Java代码实现

转载自:http://www.duzhi.me/article/864.html?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io 首先给大家介绍下什么是负载均衡(来自百科) 负载均衡 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展 网络设备和 服务器的带宽、增加 吞吐量、加强网络数据处理能力、提

小虾米的博客 5215

helloworld代码_十年架构师教你用最简单的代码实现Java基础编程—Hello World!

用Java输出HelloWorld可能有很多小伙伴在这里会有一个疑问:为什么学习每一种编程语言要学习第一个程序都是输出helloworld呢?Hello World ,中文意思:你好,世界。世界上的第一个程序就是Hello World,由Brian Kernighan创作,它简洁实用,因此它广泛适用至今。这个程序相当简单,其功能就是告知计算机显示Hello World这句话,以前程序员一般用这个程...

weixin_39934296的博客 375

【连载】优秀程序员的45个习惯之39——架构师必须写代码

架构师必须写代码 ——   高效程序员的 45 个习惯之习惯39   “我们的专家级架构师Fred会提供设计好的架构,供你编写代码。他经验丰富,拿的薪水很高,所以不要用一些愚蠢的问题或者实现上的难点,来浪费他的时间。”     软件开发业界中有许多挂着架构师称号的人。作为作者的我们,不喜欢这个称号,原因如下: 架构师 应该负责设计...

图灵教育官方博客 214
上一篇: 深入理解MySQL中的事务【超详细配图版】
下一篇: 一个完整的、全面k8s化的集群稳定架构(值得借鉴)
Java斗帝之路
博客等级 码龄7年 2392粉丝 687原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值