Refactored Code
To refactor the code to comply with the DIP we must remove the direct dependency that the TransferManager has on the BankAccount class. We could introduce a new interface for accounts that contains the methods we require to add and remove funds. However, in this case I have introduced two new interfaces. ITransferSource includes a method that allows funds to be removed from an account. ITransferDestination includes the method for adding funds to an account. The separation of the two interfaces complies with the Interface Segregation Principle (ISP) and allows for the inclusion of accounts that accept payments but cannot be the source of funds.
The BankAccount class is modified so that it implements the new interfaces. TransferManager is modified so that the Source property expects an ITransferSource object and the destination is an ITransferDestination. No direct dependencies on concrete classes now exist. Instead, both the high level class and the low level class depend upon the two abstractions.
The earlier UML diagram can now be redrawn:
The refactored code is as follows:
public interface ITransferSource
{
void RemoveFunds(decimal value);
}
public interface ITransferDestination
{
void AddFunds(decimal value);
}
public class BankAccount : ITransferSource, ITransferDestination
{
public string AccountNumber { get; set; }
public decimal Balance { get; set; }
public void AddFunds(decimal value)
{
Balance += value;
}
public void RemoveFunds(decimal value)
{
Balance -= value;
}
}
public class TransferManager
{
public ITransferSource Source { get; set; }
public ITransferDestination Destination { get; set; }
public decimal Value { get; set; }
public void Transfer()
{
Source.RemoveFunds(Value);
Destination.AddFunds(Value);
}
}
22 January 2011