其他分享
首页 > 其他分享> > 银行转账DDD案例

银行转账DDD案例

作者:互联网

银行转账事务脚本实现方式

//两个账号间,转账金额计算逻辑全部在MoneyTransferService中,Account仅仅是数据载体
public class MoneyTransferServiceTransactionScriptImpl implements MoneyTransferService {
private AccountDao accountDao;
  
    private BankingTransactionRepository bankingTransactionRepository;
 

    @Override
    public BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) {
   Account fromAccount = accountDao.findById(fromAccountId);
    Account toAccount = accountDao.findById(toAccountId);
   double newBalance = fromAccount.getBalance() - amount;
    
    //是否支持透支
        switch (fromAccount.getOverdraftPolicy()) {
     case NEVER:
        if (newBalance < 0) {
          throw new DebitException("Insufficient funds");
        }
                break;
       case ALLOWED:
        if (newBalance < -limit) {
                    throw new DebitException(
                            "Overdraft limit (of " + limit + ") exceeded: " + newBalance);
         }
        break;
    }
       fromAccount.setBalance(newBalance);
        toAccount.setBalance(toAccount.getBalance() + amount);
        BankingTransaction moneyTransferTransaction =
                new MoneyTranferTransaction(fromAccountId, toAccountId, amount);
        bankingTransactionRepository.addTransaction(moneyTransferTransaction);
        return moneyTransferTransaction;
  }
}

 

银行转账DDD实现

public class Account {
  // @Id
  private String id;
  private double balance;
  private OverdraftPolicy overdraftPolicy;
  . . .
  public double balance() { return balance; }
  public void debit(double amount) {
    this.overdraftPolicy.preDebit(this, amount);
    this.balance = this.balance - amount;
    this.overdraftPolicy.postDebit(this, amount);
  }
  public void credit(double amount) {
    this.balance = this.balance + amount;
  }

 //构造器
 public Account() {
  //构造器中根据XX创建透支策略
  if(){
    this.overdraftPolicy = new NoOverdraftAllowed();
  }else{
    
this.overdraftPolicy = new XXXX();
  }
 }
}

透支策略OverdraftPolicy不仅仅是一个Enum了,而是被抽象成包含了业务规则并采用了策略模式的对象。

 

public interface OverdraftPolicy{
  void preDebit(Account account, double amount);
  void postDebit(Account account, double amount);
}

public class NoOverdraftAllowed implements OverdraftPolicy {
  public void preDebit(Account account, double amount) {
    double newBalance = account.balance() - amount;
    if (newBalance < 0) {
      throw new DebitException("Insufficient funds");
    }
  }
  public void postDebit(Account account, double amount) {
} }
public class LimitedOverdraft implements OverdraftPolicy { private double limit; public void preDebit(Account account, double amount) { double newBalance = account.balance() - amount; if (newBalance < -limit) { throw new DebitException("Overdraft limit (of " + limit + ") exceeded: " + newBalance); } } public void postDebit(Account account, double amount) {
} }

Domain Service 只需要调用相关的Entity对象完成业务

public class MoneyTransferServiceDomainModelImpl implements MoneyTransferService {
   private AccountRepository accountRepository;
   private BankingTransactionRepository  bankingTransactionRepository;

  @Override
  public BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) {
    Account fromAccount = accountRepository.findById(fromAccountId);
    Account toAccount = accountRepository.findById(toAccountId);
    
    fromAccount.debit(amount);
    toAccount.credit(amount);
    BankingTransaction moneyTransferTransaction = new MoneyTranferTransaction(fromAccountId, toAccountId, amount);
    bankingTransactionRepository.addTransaction(moneyTransferTransaction);
    return moneyTransferTransaction;
  }
}

 

对比事务脚本,使用领域模型优势

面向对象

业务语义显性化

完全淹没在代码中,没有凸显出来

 

领域服务

有些领域动作,是一些动词,但是却不属于任何对象。它们代表了领域中的一个重要行为,所以不能忽略它们或简单把它们合并到某个实体或者值对象中。当这样的行为从领域中被识别出来,最佳方式是将它们声明成一个服务。它的作用是为了领域提供相应的功能。

Service通常以一个活动来命名,而不是Entity来命名。以转账为例,转账的这个行为就是一个领域概念,但是是发生在两个账号之间,归属于账号Entity并不合适,因为一个账号Entity没必要去关联他转账的账号Entity。这种情况下使用MoneyTransferDomainService更合适。

识别领域服务,主要看是否满足以下三个特征

 

标签:转账,Account,double,newBalance,案例,amount,balance,public,DDD
来源: https://www.cnblogs.com/MadYanYan/p/15396971.html