首页 > 其他分享 >DDD领域驱动设计(二)

DDD领域驱动设计(二)

时间:2024-03-05 10:58:02浏览次数:14  
标签:void isFrozen private amount Long 设计 驱动 public DDD

一、贫血模型和充血模型

       1.1、贫血模型

               定义:领域对象里只有get,set方法,所有的业务逻辑都不包含在内,而是放到Business Logic层              

               优点:

    1. 各层单向依赖,结构清楚,易于实现和维护。
    2. 设计简单,底层模型非常稳定。

               缺点:

    1. 领域层domain object部分比较紧密依赖持久化domain logic被分离到Service层,显得不够OO。
    2. Service过重。

                样例:三层架构  。三层架构业务中经常使用基于贫血模式的开发模式。              

Repository + Entity

Service + BO(Business Object)

Controller + VO(View Object)

代码:

 1 /**
 2  * 账户业务对象
 3  */
 4 public class AccountBO {
 5 
 6     /**
 7      * 账户ID
 8      */
 9     private String accountId;
10 
11     /**
12      * 账户余额
13      */
14     private Long balance;
15     /**
16      * 是否冻结
17      */
18     private boolean isFrozen;
19 
20     public String getAccountId() {
21         return accountId;
22     }
23 
24     public void setAccountId(String accountId) {
25         this.accountId = accountId;
26     }
27 
28     public Long getBalance() {
29         return balance;
30     }
31 
32     public void setBalance(Long balance) {
33         this.balance = balance;
34     }
35 
36     public boolean isFrozen() {
37         return isFrozen;
38     }
39 
40     public void setFrozen(boolean isFrozen) {
41         this.isFrozen = isFrozen;
42     }
43 }
44 
45 /**
46  * 转账业务服务实现
47  */
48 @Service
49 public class TransferServiceImpl implements TransferService {
50 
51     @Autowired
52     private AccountService accountService;
53 
54     @Override
55     public boolean transfer(String fromAccountId, String toAccountId, Long amount) {
56         AccountBO fromAccount = accountService.getAccountById(fromAccountId);
57         AccountBO toAccount = accountService.getAccountById(toAccountId);
58 
59         /** 检查转出账户 **/
60         if (fromAccount.isFrozen()) {
61             throw new MyBizException(ErrorCodeBiz.ACCOUNT_FROZEN);
62         }
63         if (fromAccount.getBalance() < amount) {
64             throw new MyBizException(ErrorCodeBiz.INSUFFICIENT_BALANCE);
65         }
66         fromAccount.setBalance(fromAccount.getBalance() - amount);
67 
68         /** 检查转入账户 **/
69         if (toAccount.isFrozen()) {
70             throw new MyBizException(ErrorCodeBiz.ACCOUNT_FROZEN);
71         }
72         toAccount.setBalance(toAccount.getBalance() + amount);
73 
74         /** 更新数据库 **/
75         accountService.updateAccount(fromAccount);
76         accountService.updateAccount(toAccount);
77         return Boolean.TRUE;
78     }
79 }
View Code

     1.2、充血模型

              定义:数据和对应的业务逻辑被封装到同一个类中。因此充血模型满足OOP。

          优点:

    1. 面对对象,Business Logic复核单一职责,不想在贫血模型里面那样包含所有业务逻辑,太过于沉重。

          缺点:

    1. 逻辑比较含糊。什么样的逻辑应该放到Domain Object中,什么样的业务逻辑应该放到Business Logic中。

                          切分原则:可重用度高的,和demain object状态密切关联的放到Domain Object中,可重用度低的,和domain object状态没有密切关联的放到Business Logic中。即domain logic只应该和这一个domain object的实例状态有关,而不应该和一批domain object的状态有关。

           代码:

/**
 * 账户业务对象
 */
public class AccountBO {

    /**
     * 账户ID
     */
    private String accountId;

    /**
     * 账户余额
     */
    private Long balance;

    /**
     * 是否冻结
     */
    private boolean isFrozen;

    /**
     * 出借策略
     */
    private DebitPolicy debitPolicy;

    /**
     * 入账策略
     */
    private CreditPolicy creditPolicy;

    /**
     * 出借方法
     * 
     * @param amount 金额
     */
    public void debit(Long amount) {
        debitPolicy.preDebit(this, amount);
        this.balance -= amount;
        debitPolicy.afterDebit(this, amount);
    }

    /**
     * 转入方法
     * 
     * @param amount 金额
     */
    public void credit(Long amount) {
        creditPolicy.preCredit(this, amount);
        this.balance += amount;
        creditPolicy.afterCredit(this, amount);
    }

    public boolean isFrozen() {
        return isFrozen;
    }

    public void setFrozen(boolean isFrozen) {
        this.isFrozen = isFrozen;
    }

    public String getAccountId() {
        return accountId;
    }

    public void setAccountId(String accountId) {
        this.accountId = accountId;
    }

    public Long getBalance() {
        return balance;
    }

    /**
     * BO和DO转换必须加set方法这是一种权衡
     */
    public void setBalance(Long balance) {
        this.balance = balance;
    }

    public DebitPolicy getDebitPolicy() {
        return debitPolicy;
    }

    public void setDebitPolicy(DebitPolicy debitPolicy) {
        this.debitPolicy = debitPolicy;
    }

    public CreditPolicy getCreditPolicy() {
        return creditPolicy;
    }

    public void setCreditPolicy(CreditPolicy creditPolicy) {
        this.creditPolicy = creditPolicy;
    }
}


/**
 * 入账策略实现
 */
@Service
public class CreditPolicyImpl implements CreditPolicy {

    @Override
    public void preCredit(AccountBO account, Long amount) {
        if (account.isFrozen()) {
            throw new MyBizException(ErrorCodeBiz.ACCOUNT_FROZEN);
        }        
    }

    @Override
    public void afterCredit(AccountBO account, Long amount) {
        System.out.println("afterCredit");
    }
}

/**
 * 出借策略实现
 */
@Service
public class DebitPolicyImpl implements DebitPolicy {

    @Override
    public void preDebit(AccountBO account, Long amount) {
        if (account.isFrozen()) {
            throw new MyBizException(ErrorCodeBiz.ACCOUNT_FROZEN);
        }
        if (account.getBalance() < amount) {
            throw new MyBizException(ErrorCodeBiz.INSUFFICIENT_BALANCE);
        }
    }

    @Override
    public void afterDebit(AccountBO account, Long amount) {
        System.out.println("afterDebit");
    }
}

/**
 * 转账业务服务实现
 */
@Service
public class TransferServiceImpl implements TransferService {

    @Resource
    private AccountService accountService;
    @Resource
    private CreditPolicy creditPolicy;
    @Resource
    private DebitPolicy debitPolicy;

    @Override
    public boolean transfer(String fromAccountId, String toAccountId, Long amount) {
        AccountBO fromAccount = accountService.getAccountById(fromAccountId);
        AccountBO toAccount = accountService.getAccountById(toAccountId);
        fromAccount.setDebitPolicy(debitPolicy);
        toAccount.setCreditPolicy(creditPolicy);

        fromAccount.debit(amount);
        toAccount.credit(amount);
        accountService.updateAccount(fromAccount);
        accountService.updateAccount(toAccount);
        return Boolean.TRUE;
    }
}
View Code

          1.3、总结

                   贫血模型在传统开发模式更受欢迎。充血模型用于更加复杂的业务系统,更具优势。

 

标签:void,isFrozen,private,amount,Long,设计,驱动,public,DDD
From: https://www.cnblogs.com/xiaobaicai12138/p/18053432

相关文章

  • 基于Ant Design设计语言的WinForm UI界面库
    前言经常在技术群里看到有小伙伴提问:WinForm有什么好看、开源的UI库推荐的吗?,今天大姚给大家分享一款基于AntDesign(使用AntDesign5.0)设计语言、开源(ApacheLicense)的WinFormUI界面库:AntdUI。假如你有好用的WinFormUI库推荐,欢迎文末留言......
  • 深入解析ASP.NET Core MVC应用的模块化设计[上篇]
    ASP.NETCoreMVC的“模块化”设计使我们可以构成应用的基本单元Controller定义在任意的模块(程序集)中,并在运行时动态加载和卸载。这种为“飞行中的飞机加油”的方案是如何实现的呢?该系列的两篇文章将关注于这个主题,本篇着重介绍“模块化”的总体设计,下篇我们将演示将介绍“分散定......
  • 【游戏设计笔记】游戏设计师的一些自用学习网站/论坛/书籍
    网站:1.游资网:https://www.gameres.com/里面不仅仅局限于策划,还有美术和程序的一些内容,包括一些最新的资讯,技术讨论,设计思路等等里面都有分享 2.独立精神:https://indienova.com/里面会有一些比较硬核的干货,大佬也很多!不仅有论坛讨论和文章分享还有一些独游组队项目哦 ......
  • 新零售SaaS架构:订单履约系统的概念模型设计
    订单履约系统的概念模型订单:客户提交购物请求后,生成的买卖合同,通常包含客户信息、下单日期、所购买的商品或服务明细、价格、数量、收货地址以及支付方式等详细信息。子订单:为了更高效地进行履约,大订单可能会被拆分成多个子订单,子订单会根据商品类型、配送地址、仓库位置或......
  • 电赛之星崛起:无名创新助力2024电子设计竞赛奖学金,你准备好了吗?
    动详情介绍网址:www.nameless.tech/space.html   电赛之星崛起:无名创新助力2024电子设计竞赛奖学金,你准备好了吗?一、活动流程1、获得助力资格1、邀请志同道合的同学组队参加校内选拔赛,成功晋级并获得参加省赛的资格,出线的队伍会得到学校、实验室及指导老师的经费支持。2......
  • AP5193 降压恒流IC PWM 线性调光 5-100V 2.5A LED汽车灯驱动芯片
    产品  AP5193是一款PWM工作模式,效率、简单、内置功率MOS管,适用于4.5-100V输入的高精度降压LED恒流驱动芯片。电流2.5A。AP5193可实现线性调光和PWM调光,线性调光脚有效电压范围0.55-2.6V.AP5193工作频率可以通过RT外部电阻编程来设定,同时内置抖频电路,可以降低对其他设备的EM......
  • 驱动Driver-新字符设备驱动
    分配和释放设备号存在的问题alloc_chrdev_regionunregister_chrdev_region......
  • 设计方案、实施方案的重要性
    开发一个软件的设计方案和实施方案的重要性是不可忽视的。以下是它们的重要性:设计方案的重要性:需求理解和定义:设计方案帮助团队全面理解客户需求,并将其转化为可执行的计划和规范,确保软件开发符合用户期望。系统架构规划:设计方案确定系统的整体架构、模块划分、数据流和交互......
  • 一款基于Vue3实现的漂亮且功能强大的在线海报设计器
    大家好,我是Java陈序员。我们在工作中经常需要设计各种各样的图片,海报、产品图、文章图片、视频/公众号等。我们可以选择使用PS来设计图片,但是有时候想快速完成任务,有没有一款工具支持快速生成海报呢?答案是有的,今天给大家介绍一款在线图片(海报)设计器。关注微信公众号:【Java......
  • 没想到,JDBC 驱动会偷偷修改 sql_mode 的会话值
    最近碰到一个case,值得分享一下。现象就是一个update操作,在mysql客户端中执行提示warning,但在java程序中执行却又报错。问题重现mysql> create table test.t1(id int primary key, c1 datetime);Query OK, 0 rows affected (0.01 sec)mysql> insert int......