设计模式(一):DDD领域驱动设计

news2025/1/17 22:55:02
  • DDD重架构,轻业务! – 从单体架构开始快速验证
  • DDD设计模式
    • 贫血模型
    • 充血模型
    • 防腐层
  • DDD四层架构规范
  • DDD单体架构和微服务架构隔离
    • 本地单体SPI 插拔式扩展业务模式
    • Nacos 插拔式扩展业务模式 ---- 服务名作为服务service code
  • DDD清晰架构 – 构建领域仓库,实现领域复用

领域驱动设计(DDD)在爱奇艺打赏业务的实践

https://blog.csdn.net/weixin_45583158/article/details/114312926

DDD重架构,轻业务!— 从单体架构开始快速验证

在这里插入图片描述

DDD设计模式

1. 贫血模型

  • POJO 没有业务
  • 业务交由Service处理

2. 充血模型

  • DAO 负责和业务映射
  • DO 负责DB映射

3. 防腐层

  • 封控封装 BusiSafeService
  • Kafak封装 AduitMessageProducer
  • 金额计算 AccountTransferService
  • 用实体(Entity)封装单对象的状态行为
  • 领域服务封装多实体逻辑

变化前

public class PaymentController{
    private PayService payService;
    public Result pay(String merchantAccount,BigDecimal amount){
        Long userId = (Long) session.getAttribute("userId");
  return payService.pay(userId, merchantAccount, amount);
    }
}

public class PayServiceImpl extends PayService{
    private AccountDao accountDao;//操作数据库
    private KafkaTemplate<String, String> kafkaTemplate;//操作kafka
    private RiskCheckService riskCheckService;//风控微服务接口
    
    public Result pay(Long userId,String merchantAccount,BigDecimal amount){
        // 1. 从数据库读取数据
        AccountDO clientDO = accountDAO.selectByUserId(userId);
        AccountDO merchantDO =
        accountDAO.selectByAccountNumber(merchantAccount);
        // 2. 业务参数校验
        if (amount>(clientDO.getAvailable()) {
         throw new NoMoneyException();
        }
        // 3. 调用风控微服务
        RiskCode riskCode = riskCheckService.checkPayment(...);
        // 4. 检查交易合法性
        if("0000"!= riskCode){
            throw new InvalideOperException();
        }
        // 5. 计算新值,并且更新字段
        BigDecimal newSource = clientDO.getAvailable().subtract(amount);
        BigDecimal newTarget = merchantDO.getAvailable().add(amount);
        clientDO.setAvailable(newSource);
        merchantDO.setAvailable(newTarget);
        // 6. 更新到数据库
        accountDAO.update(clientDO);
        accountDAO.update(merchantDO);
        // 7. 发送审计消息
        String message = sourceUserId + "," + targetAccountNumber + "," + targetAmount;
        kafkaTemplate.send(TOPIC_AUDIT_LOG, message);
        return Result.SUCCESS;
    }
}

变化后

public class PaymentController{
    private PayService payService;
    public Result pay(String merchantAccount,BigDecimal amount){
        Long userId = (Long) session.getAttribute("userId");
  return payService.pay(userId, merchantAccount, amount);
    }
}

public class PayServiceImpl extends PayService{
    private AccountRepository accountRepository;
    private AuditMessageProducer auditMessageProducer;
    private BusiSafeService busiSafeService;
    private AccountTransferService accountTransferService;
    
    public Result pay(Long userId,String merchantAccount,BigDecimal amount){
        // 参数校验
        Money money = new Money(amount);
        UserId clientId = new UserId(userId);
        AccountNumber merchantNumber = new AccountNumber(merchantAccount);
        // 读数据
        Account clientAccount = accountRepository.find(clientId);
        Account merAccount = accountRepository.find(merchantNumber);
        // 交易检查
        Result preCheck =  busiSafeService.checkBusi(clientAccount,merAccount,money);
        if(preCheck != Result.SUCCESS)return Result.REJECT;// 业务逻辑
  accountTransferService.transfer(clientAccount,merAccount,money);
        // 保存数据
        accountRepository.save(clientAccount);
        accountRepository.save(merAccount);
        // 发送审计消息
        AuditMessage message = new AuditMessage(clientAccount, merAccount,money);
  auditMessageProducer.send(message);
        return Result.SUCCESS;
    }
}

DDD四层架构规范

  1. 领域层(Domain Layer): 系统的核心,纯粹表达业务能力,不需要任何外部依赖
  2. 应用层(Application Layer):协调领域对象,组织形成业务场景,只依赖于领域层
  3. 用户层(User Interface):负责与用户进行交互。理解用户请求,返回用户响应。只依赖于应用层
  4. 基础层(Infrastructure Layer):业务与数据分离。为领域层提供持久化服务,为其它层提供通用能力

在这里插入图片描述

adaptor 隔离各服务层
在这里插入图片描述

DDD单体架构和微服务架构隔离

//TODO 单体架构与微服务架构只需要切换一个服务实现类即可,对各领域的核心是没有影响的。。
//@Resource(name = "LocalAsyncBusiService") //基于SPI实现的单体架构消息处理服务
@Resource(name = "NacosAsyncBusiService") //基于Nacos实现的微服务消息处理服务
private AsyncBusiService asyncBusiService;

本地单体SPI 插拔式扩展业务模式

@Component
public class BusiServiceRepositoryimpl implements BusiServiceRepository {

    private List<GsService> busiServices = new ArrayList<>();

    @PostConstruct
    public void loadBusiServices() {
        if (busiServices.isEmpty()) {
            final ServiceLoader<GsService> gsServices = ServiceLoader.load(GsService.class);
            final Iterator<GsService> iterator = gsServices.iterator();
            while (iterator.hasNext()) {
                busiServices.add(iterator.next());
            }
        }
    }

    public GsService getGsService(String serviceCode) {
        for (GsService gsService : busiServices) {
            if (serviceCode.equals(gsService.serviceCode())) {
                return gsService;
            }
        }
        return null;
    }
}

Nacos 插拔式扩展业务模式 ---- 服务名作为服务service code

@Resource
private DiscoveryClient discoveryClient;

//1、去Nacos上获取服务实例。
List<ServiceInstance> instances = discoveryClient.getInstances(serviceCode);
//1-1、如果服务不存在,直接返回不支持的serviceCode
if(null == instances || instances.isEmpty()){
    logger.error("ServiceCode["+serviceCode+"] is not support yet.");
    return;
}
StringBuffer requestUrl = new StringBuffer("http://");
ServiceInstance serviceInstance;
//随机找一个实例
if(instances.size()==1){
    serviceInstance = instances.get(0);
}else{
    Random random = new Random();
    int index = random.nextInt(instances.size());
    serviceInstance = instances.get(index);
}
//接口路径固定请求 SERVICE_SUFFIX
requestUrl.append(serviceInstance.getHost()).append(":").append(serviceInstance.getPort()).append(SERVICE_SUFFIX);

DDD清晰架构 – 构建领域仓库,实现领域复用

https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/

在这里插入图片描述

体现形式
在这里插入图片描述
消息契约层: 在很多MVC项目的开发过程当中,会将传递数据的POJO,划分成DTO、VO、BO、DO等各种各样的Object,并且不断规定在每一个技术层面使用不同的Object,其目的也是为了尽量保证每一层的数据更纯洁,减少外部数据的影响

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

加解密与HTTPS(5)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e;咱们大学读完之后有毕业证书&#xff0c;并且这个证书可以在学信网查询。专业上有注会、CCIE、律师证等&#xff0c;可以在国家职业认证机构或委托机构的网站上查…

【UCIe】UCIe DLP/DLLP 介绍

&#x1f525;点击查看精选 UCIe 系列文章&#x1f525; &#x1f525;点击进入【芯片设计验证】社区&#xff0c;查看更多精彩内容&#x1f525; &#x1f4e2; 声明&#xff1a; &#x1f96d; 作者主页&#xff1a;【MangoPapa的CSDN主页】。⚠️ 本文首发于CSDN&#xff0…

DNS协议——域名解析

DNS协议 DNS协议是一个应用层协议&#xff0c;作用是域名解析   使用DNS协议的原因&#xff0c;就是因为哪怕是点分十进制&#xff0c;对于我们都不太友好&#xff0c;因此使用域名来代替IP地址&#xff0c;比如www.baidu.com   最开始的时候&#xff0c;DNS系统只是一个普…

java基于ssm的个人博客系统个人博客网站个人博客项目源码

简介 Java ssm开发的个人博客系统&#xff0c;可以发布博客&#xff0c;照片&#xff0c;站长留言。 演示视频 https://www.bilibili.com/video/BV1sf4y1y7Ne/?share_sourcecopy_web&vd_sourceed0f04fbb713154db5cc611225d92156 技术 mysql,SSM,css,js,jq 功能 简单…

laravel5.5之laravel-admin的使用

目录 一、首先确保安装好了laravel&#xff0c;并且数据库连接设置正确 二、运行下面的命令来发布资源 三 、后台项目文件 四、静态文件 五、访问后台 六、参考文档 一、首先确保安装好了laravel&#xff0c;并且数据库连接设置正确 composer require encore/laravel-adm…

Verilog语法笔记(夏宇闻第三版)-简单的Verilog HDL模块

目录 简单的Verilog HDL程序介绍&#xff1a; 模块的结构 &#xff1a; 模块的端口定义&#xff1a; 模块内容&#xff1a; I/O说明的格式&#xff1a; 内部信号说明&#xff1a; 功能定义&#xff1a; 简单的Verilog HDL程序介绍&#xff1a; 下面先介绍几个简单的Veri…

高可用Keepalived在Linux中的应用

一、高可用 1.高可用介绍 &#xff08;1&#xff09;普通理解 两台服务器启动相同的业务系统&#xff0c;当有一台机器宕机&#xff0c;另外一台服务器快速接管服务&#xff0c;对于用户来讲是无感知的。 &#xff08;2&#xff09;专业理解 高可用是分布式系统架构设计中必…

Linux安装Docker与基本使用

Docker 常用于服务部署的一种方案 准备 1.云服务器或者虚拟机 2.Centos 系统 3.下载XFtp 和 XShell 安装Docker 首先删除系统中旧版本Docker或者残留文件 #卸载所有 yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-lo…

Spring从入门到精通 | 动力节点老杜

目录 一、Spring启示录 1、OCP开闭原则 2、依赖倒置原则&#xff08;DIP原则&#xff09; 3、控制反转&#xff08;重点&#xff09; 4、Spring框架&#xff08;重点&#xff09; 二、Spring概述 Spring的8大模块 ​编辑 Spring特点 1、轻量 2、控制反转IOC 3、面向…

Qt Mac阻止和启用休眠

阻止电脑休眠&#xff0c;在win下是使用win api实现的&#xff0c;用Qt跨平台开发&#xff0c;实现Mac的阻止休眠&#xff0c;也需要Mac本身的api来实现。经过网上查资料&#xff0c;找到了一个能用的&#xff0c;链接如下。原生mac开发用的是Object-c&#xff0c;所以该实现用…

Kyligence 客户案例“泰康集团精细化经营分析与运营平台”获评数据智能最佳实践案例

近日&#xff0c;“2022 爱分析中国数据智能最佳实践案例”评选结果正式揭晓。Kyligence 携手泰康集团申报的“泰康集团精细化经营分析与运营平台”项目经过多轮角逐脱颖而出&#xff0c;最终获评“中国数据智能最佳实践案例”。同时&#xff0c;Kyligence 通过综合能力评估&am…

Linux Shell脚本编程提高

Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到内核,不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序.Shel编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应…

保姆级教程 | 将Oxylabs住宅代理和数据中心代理与MultiLogin集成的操作步骤

MultiLogin是一款集多账户管理、浏览器指纹隐藏等功能于一体的实用解决方案。在您抓取所需公共数据时&#xff0c;将MultiLogin与值得信赖的代理结合使用&#xff0c;可以大幅降低被网站阻止情况发生的概率。 在本篇教程中&#xff0c;将带您学习简单的集成流程&#xff0c;手把…

数说热点 | 2022商业地产的“破局”与“新生”——逆境之下探索新兴可能

2022年&#xff0c;受国内新冠肺炎疫情因素影响&#xff0c;我国经济下行压力明显加大&#xff0c;尤其是部分产业链、供应链受到冲击&#xff1b;部分区域接触型、聚集型特征明显的线下消费表现低迷&#xff0c;给实体商业经营带来挑战。从市场表现看&#xff0c;2022年1-9月&…

数据架构之数据血缘:数据从哪里来,到哪里去

为了直观的感受数据血缘&#xff0c;先从网上找了两张典型的数据血缘的图。下图特点是按照数据仓库数据管理模型给出了基于表&#xff08;实体&#xff09;的数据血缘图。 此图是截取Solidatus软件生成的数据血缘图&#xff0c;该图与上图的区别在于给出了基于属性的数据血缘图…

【纯净题目版】笔试题-2023禾赛-FPGA

题目背景 笔试时间&#xff1a;2022.06.22应聘岗位&#xff1a;FPGA开发工程师 题目评价 难易程度&#xff1a;★★☆☆☆知识覆盖&#xff1a;★☆☆☆☆超纲范围&#xff1a;☆☆☆☆☆值得一刷&#xff1a;★☆☆☆☆ 文章目录1. 使用最少的电路实现二分频&#xff0c;给出…

ubuntu20.04 arm-linux-gnueabihf交叉编译opencv4.7.0 与opencv-contrib-4.7.0

安装交叉编译工具链编译的目标硬件是RV1126&#xff0c;编译工具链为32位的arm-linux-gnueabihf&#xff0c;本次使用的是8.3版本&#xff0c;可在Downloads | GNU-A Downloads – Arm Developer进行下载。下载后&#xff0c;解压到自己的安装目录&#xff0c;比如解压到/opt目…

Seata客户端

一个调用链中的所有微服务都是seata的客户端&#xff0c;都必须走下面的步骤 第一步&#xff1a;创建undo_log表 下载地址&#xff1a;https://github.com/seata/seata/tree/develop/script/client/at/db -- for AT mode you must to init this sql for you business databa…

海南三亚游记2022-2023跨年

文章目录1、概述2、交通2.1、广州飞三亚2.2、做高铁&#xff0c;三亚到海口2.3、海口飞广州3、风景3.1、吉阳区3.2、天涯区4、美食5、住宿6、补充2014年海南游记1、概述 2022-12-30~2023-01-04&#xff0c;海南三亚游记&#xff0c;旨在记录攻略 之前已经去过海南2次&#xff…

数据结构的相关概念

基本概念和术语 数据是对客观信息的一种描述&#xff0c;它是由能被计算机识别与处理的数值、字符等符号构成的集合。 数据元素是数据的基本单位&#xff0c;在计算机程序中通常作为一个整体进行考虑和处理。 关键码值的是数据元素中能起标识作用的数据项。 关系指的是集合…