这里的“某种方式”显然是指银行账户不允许引用的服务。这意味着这并不是一个很好的隔离领域模型的例子。
虽然
BankAccount
本身没有对这个服务的引用,但它仍然可以与这样的服务进行交互。
举个更简单的例子,让我们来看一下利息的计算。天真的方法可能是:
public BankAccount
{
public decimal Balance { get; set; }
public decimal Interest { get; set; }
private public List<Transaction> transactions = new List<Transaction>();
public List<Transaction> Transactions { get { return transactions; } }
public decimal CalculateInterest()
{
return Balance * Interest;
}
}
BankAccount account = ...;
var interest = account.CalculateInterest();
account.Balance += interest;
account.AddTransaction(new Transaction() { Description = "Monthly Interest", Amount = interest });
这样做不好,因为你现在有混合责任。计算利息不是BankAccount类的重点,而且它现在涉及到多个责任,比如计算,这可能会随着几个因素的变化或依赖而改变。
public BankAccount
{
public decimal Balance { get; private set; }
public AccountType AccountType { get; private set; }
private public List<Transaction> transactions = new List<Transaction>();
public IEnumerable<Transaction> Transactions { get { return transactions.AsEnumerable(); } }
public void CalculateInterest(IInterestCalculator calc)
{
decimal interest = calc.CalculateInterest(this);
this.AddTransaction(new Transaction() { Description = "Monthly Interest", Amount = interest });
}
public void AddTransaction(Transaction transaction)
{
var newBalance = this.Balance + transaction.Balance;
if(this.transaction.Amount < 0 && newBalance < this.Limit)
{
throw new NotEnoughFundsException();
}
this.transactions.Add(transaction);
this.Balance = newAmount;
}
}
public interface IInterestCalculator
{
decimal CalculateInterest(Bankaccount);
}
public class DefaultAccountInterestCalculator : IInterestCalculator
{
public decimal CalculateInterest(BankAccount account)
{
return account.Balance * 0.02;
}
}
public class PremiumAccountInterestCalculator : IInterestCalculator
{
private const decimal Threshold = 10000m;
public decimal CalculateInterest(BankAccount account)
{
if(account.Balance > Threshold)
{
return (decimal)((Threshold * 0.02) + (account.Balance-Threshold) * 0.03);
}
else
{
return (decimal)(account.Balance * 0.02);
}
}
}
您的服务中
BankAccount account = ...;
IInterestCalculator calculator = (account.AccountType == AccountType.Premium)?new PremiumAccountInterestCalculator():DefaultAccountInterestCalculator();
BankAccount account.CalculateInterest(calculator);
现在你的
BankAccount
类只有一个职责,即维护其状态和所需的业务逻辑(例如检查余额是否足够,仅允许通过方法操作银行账户而不是直接更改
Balance
或操纵
List<Transaction>
)。
计算由计算器类完成,这些类被传递到
BankAccount
的
CalculateInterest
方法中。服务包含所需的逻辑,既不适合计算器也不适合银行账户类。
简而言之:业务逻辑(在丰富的领域模型中)是维护类的状态所需的所有逻辑,并尽可能地将其封装起来。在第二个类中,不能直接更改余额。需要
AddTransaction
或
CalculateInterest
(用于计算利息)。
这保证了(假设它是
并发安全的)
Balance
和
Transactions
始终处于一致的状态(即永远不会漏掉添加任何交易或更新余额)。