从头捋一遍Java项目中的五大设计原则,就不信你学不会!(中)

简介: 从头捋一遍Java项目中的五大设计原则,就不信你学不会!(中)

接着可以将注册逻辑拆解为注册处理器和使用注册处理器的service模块:


/**
 * @Author linhao
 * @Date created in 7:56 上午 2021/9/3
 */
public interface IRegisterService {
    /**
     * 用户注册之后处理函数
     *
     * @param registerInputParam 用户注册之后的传入参数
     */
    void postProcessorAfterRegister(RegisterInputParam registerInputParam);
}


注册处理器内部才是真正的核心部分:


/**
 * @Author linhao
 * @Date created in 8:10 上午 2021/9/3
 */
public abstract class AbstractRegisterHandler {
    /**
     * 获取注册渠道ID
     *
     * @return
     */
    public abstract int getSource();
    /**
     * 注册之后的核心通知模块程序
     *
     * @param registerInputParam
     * @return
     */
    public abstract boolean doPostProcessorAfterRegister(RegisterInputParam registerInputParam);
}


具体的实现交给了各个Handler组件:


公众号注册渠道的后置处理器


/**
 * @Author linhao
 * @Date created in 8:16 上午 2021/9/3
 */
public class GZHRegisterHandler  extends AbstractRegisterHandler {
    @Override
    public int getSource() {
        return RegisterConstants.RegisterEnum.GZH_CHANNEL.getCode();
    }
    @Override
    public boolean doPostProcessorAfterRegister(RegisterInputParam registerInputParam) {
        System.out.println("公众号处理逻辑");
        return true;
    }
}


app注册渠道的后置处理器


/**
 * @Author linhao
 * @Date created in 8:16 上午 2021/9/3
 */
public class AppRegisterHandler extends AbstractRegisterHandler {
    @Override
    public int getSource() {
        return RegisterConstants.RegisterEnum.APP_CHANNEL.getCode();
    }
    @Override
    public boolean doPostProcessorAfterRegister(RegisterInputParam registerInputParam) {
        System.out.println("app处理逻辑");
        return true;
    }
}


不同的注册渠道号通过一个枚举来进行管理:


public class RegisterConstants {
    public enum RegisterEnum{
        GZH_CHANNEL(0,"公众号渠道"),
        APP_CHANNEL(1,"app渠道");
        RegisterEnum(int code, String desc) {
            this.code = code;
            this.desc = desc;
        }
        int code;
        String desc;
        public int getCode() {
            return code;
        }
    }
}


接下来,对于注册的后置处理服务接口进行实现:


/**
 * @Author linhao
 * @Date created in 7:48 上午 2021/9/3
 */
public class RegisterServiceImpl implements IRegisterService {
    private static List<AbstractRegisterHandler> registerHandlerList = new ArrayList<>();
    static {
        registerHandlerList.add(new GZHRegisterHandler());
        registerHandlerList.add(new AppRegisterHandler());
    }
    @Override
    public void postProcessorAfterRegister(RegisterInputParam registerInputParam) {
        for (AbstractRegisterHandler abstractRegisterHandler : registerHandlerList) {
            if(abstractRegisterHandler.getSource()==registerInputParam.getSource()){
                abstractRegisterHandler.doPostProcessorAfterRegister(registerInputParam);
                return;
            }
        }
        throw new RuntimeException("未知注册渠道号");
    }
}


最后通过简单的一段测试程序:


public class Test {
    public static void main(String[] args) {
        RegisterInputParam registerInputParam = new RegisterInputParam();
        registerInputParam.setUserId(10012);
        registerInputParam.setSource(0);
        IRegisterService registerService = new RegisterServiceImpl();
        registerService.postProcessorAfterRegister(registerInputParam);
        RegisterInputParam registerInputParam2 = new RegisterInputParam();
        registerInputParam2.setUserId(10013);
        registerInputParam2.setSource(1);
        registerService.postProcessorAfterRegister(registerInputParam2);
        System.out.println("=======");
    }
}


这样的设计和起初最先前的设计相比有几处不同的完善点:


新增不同注册渠道的时候,只需要关心注册渠道的source参数。


同时对于后续业务的拓展,新增不同的注册渠道的时候,RegisterServiceImpl只需要添加新编写的注册处理器类即可。


image.png


再回过头来看,这样的一段代码设计是否满足了开放封闭原则呢?


每次新增不同的注册类型处理逻辑之后,程序中都只需要新增一种Handler处理器,这种处理器对于原先的业务代码并没有过多的修改,从整体设计的角度来看,并没有对原有的代码结构造成影响,而且灵活度相比之前有所提高。这也正好对应了,对扩展开放,对修改关闭。


如果你对设计模式有一定了解的话,可能还会发现大多数常用的设计模式都在遵守这一项原则,例如模版模式,策略模式,责任链模式等等。


里氏替换原则


我认为,里氏替换原则更多是体现在了父子类继承方面,强调的是子类在继承了父类对象的时候不应该破坏这个父类对象的设计初衷。


举个例子来说:


我们定义了一个提款的服务:


/**
 * @Author linhao
 * @Date created in 11:21 上午 2021/9/4
 */
public interface DrawMoneyService {
    /**
     * 提款函数
     *
     * @param drawMoneyInputParam
     */
    void drawMoney(DrawMoneyInputParam drawMoneyInputParam);
}


对应的是一个抽象实现父类:


/**
 * @Author linhao
 * @Date created in 11:25 上午 2021/9/4
 */
public abstract class AbstractDrawMoneyServiceImpl implements DrawMoneyService{
    /**
     * 设计初衷,需要对提现金额进行参数校验
     * 
     * @param drawMoneyInputParam
     */
    @Override
    public abstract void drawMoney(DrawMoneyInputParam drawMoneyInputParam);
}
相关文章
|
3月前
|
关系型数据库 MySQL Java
【MySQL+java+jpa】MySQL数据返回项目的感悟
【MySQL+java+jpa】MySQL数据返回项目的感悟
53 1
|
3月前
|
编解码 Oracle Java
java9到java17的新特性学习--github新项目
本文宣布了一个名为"JavaLearnNote"的新GitHub项目,该项目旨在帮助Java开发者深入理解和掌握从Java 9到Java 17的每个版本的关键新特性,并通过实战演示、社区支持和持续更新来促进学习。
101 3
|
7天前
|
Java Maven
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
在Java项目中,启动jar包时遇到“no main manifest attribute”错误,且打包大小明显偏小。常见原因包括:1) Maven配置中跳过主程序打包;2) 缺少Manifest文件或Main-Class属性。解决方案如下:
java项目中jar启动执行日志报错:no main manifest attribute, in /www/wwwroot/snow-server/z-server.jar-jar打包的大小明显小于正常大小如何解决
|
4天前
|
存储 Java BI
java怎么统计每个项目下的每个类别的数据
通过本文,我们详细介绍了如何在Java中统计每个项目下的每个类别的数据,包括数据模型设计、数据存储和统计方法。通过定义 `Category`和 `Project`类,并使用 `ProjectManager`类进行管理,可以轻松实现项目和类别的数据统计。希望本文能够帮助您理解和实现类似的统计需求。
40 17
|
26天前
|
NoSQL Java 关系型数据库
Liunx部署java项目Tomcat、Redis、Mysql教程
本文详细介绍了如何在 Linux 服务器上安装和配置 Tomcat、MySQL 和 Redis,并部署 Java 项目。通过这些步骤,您可以搭建一个高效稳定的 Java 应用运行环境。希望本文能为您在实际操作中提供有价值的参考。
119 26
|
2月前
|
XML Java 测试技术
从零开始学 Maven:简化 Java 项目的构建与管理
Maven 是一个由 Apache 软件基金会开发的项目管理和构建自动化工具。它主要用在 Java 项目中,但也可以用于其他类型的项目。
61 1
从零开始学 Maven:简化 Java 项目的构建与管理
|
2月前
|
Java
Java项目中高精度数值计算:为何BigDecimal优于Double
在Java项目开发中,涉及金额计算、面积计算等高精度数值操作时,应选择 `BigDecimal` 而非 `Double`。`BigDecimal` 提供任意精度的小数运算、多种舍入模式和良好的可读性,确保计算结果的准确性和可靠性。例如,在金额计算中,`BigDecimal` 可以精确到小数点后两位,而 `Double` 可能因精度问题导致结果不准确。
|
2月前
|
Java Android开发
Eclipse 创建 Java 项目
Eclipse 创建 Java 项目
51 4
|
2月前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
51 3
|
2月前
|
前端开发 Java 数据库
如何实现一个项目,小白做项目-java
本教程涵盖了从数据库到AJAX的多个知识点,并详细介绍了项目实现过程,包括静态页面分析、数据库创建、项目结构搭建、JSP转换及各层代码编写。最后,通过通用分页和优化Servlet来提升代码质量。
70 1