Factory Design Pattern

In the previous post I had mentioned about Factory Design Pattern. We already had an implementation alongside the Strategy Design pattern. In this post I would like to talk in detail about the Factory Design Pattern. The primary use of factory pattern is to encapsulate the object creation logic from the client. Factory pattern is a creational pattern which helps decoupling the consumers of a class from creating a new instance. Every time we use a new keyword we are tightly coupling the class and its consumer. Factory pattern is also useful when we have a common interface from which we can choose one of the option to create an instance.

Problem Statement

Assume that we are building software for a bank. Customers of the bank are entitled to receive the account statement. They can choose the mode of delivery for the statement. It can be a physical statement or an electronic account statement. Based on the customer preference the account statement will be delivered to the customer either in physical paper format or an electronic format in an email.

Solution

Similar to the previous post, I don’t intend to use any user interface for this post. Here is a simple AccountStatement class which has a method called DispatchStatement. Based on the input parameter dispatch mode we construct either the PhysicalStatementDispatcher or ElectronicStatementDispatcher instance.

    public class AccountStatement

    {

        public void DispatchStatement(DispatchMode dispatchMode)

        {

            IStatementDispatcher dispatcher = null;

 

            if (dispatchMode.Equals(DispatchMode.Physical))

            {

                dispatcher = new PhysicalStatementDispatcher

                    {

                        UnitNumber = 101,

                        BuildingNumber = 100,

                        Street = "Little India",

                        PostalCode = 123456

                    };

            }

            else if (dispatchMode.Equals(DispatchMode.Electronic))

            {

                dispatcher = new ElectronicStatementDispatcher

                    {

                        Email = "[email protected]",

                        AlternateEmail = "[email protected]"

                    };

            }

 

            if (dispatcher != null)

            {

                dispatcher.Dispatch();

            }

        }

    }

The settings varies based on the type of dispatcher. For the physical statement we specify the details related to the postal address. For the Electronic statement we specify the email address. Finally the Dispatch method is called on the dispatcher instance to dispatch the statement. For simplicity I have hardcoded the values. In real applications these values would come from some persistent data store like database. 

Problem with this approach

The problem with this approach are similar to the ones with the previous example related to Strategy pattern. The SRP as well as OCP is violated. The DispatchStatement method contains more than one responsibility. This method knows way too many things like the email address and the postal address of the customer which are not really necessary. Lets try to refactor the solution towards using the Factory pattern. The Factory pattern is a creational pattern which is used to encapsulate the creational logic. In our case we are creating an instance of the dispatcher based on the type of dispatch mode.

Refactored Solution

The refactored solution is much simpler and easier to implement.

    public class AccountStatement

    {

        public void DispatchStatement(DispatchMode dispatchMode)

        {

            IStatementDispatcher dispatcher = StatementDispatcherFactory.CreateDispatcher(dispatchMode);

 

            if (dispatcher != null)

            {

                dispatcher.Dispatch();

            }

        }

    }

The complete portion of creation of the dispatcher has been moved to the factory. DispatchStatement method delegates the call to CreateDispatcher by passing the dispatch mode. The StatementDispatcherFactory is very simple with just the same code moved from AccountStatement class.

    public static class StatementDispatcherFactory

    {

        public static IStatementDispatcher CreateDispatcher(DispatchMode dispatchMode)

        {

            IStatementDispatcher dispatcher = null;

 

            if (dispatchMode == DispatchMode.Physical)

            {

                dispatcher = new PhysicalStatementDispatcher

                {

                    UnitNumber = 101,

                    BuildingNumber = 100,

                    Street = "Little India",

                    PostalCode = 123456

                };

            }

            else if (dispatchMode == DispatchMode.Electronic)

            {

                dispatcher = new ElectronicStatementDispatcher

                {

                    Email = "[email protected]",

                    AlternateEmail = "[email protected]"

                };

            }

 

            return dispatcher;

        }

    }

By moving the creational logic to the factory we have made the AccountStatement class extensible. We can add more number of dispatchers in future without modifying the AccountStatment class. The OCP is satisfied by moving the creational logic to the factory.

The other advantage of using the factory is the client need not be aware of the complex construction process. In future we can change the implementation of the one or more dispatcher without impacting the client. Say for example the PhysicalStatementDispatcher is currently using the postal service to deliver the statement and decides to change and use a low cost courier service for delivery of physical statements. This change can be implemented without modifying the AccountStatement class. The account statement class does not need to know who is the provider for the courier service.

Conclusion

Factories are very useful when certain decisions are to be made at runtime based on user preferences or environment settings. By encapsulating the creational logic in a central location we can ensure that changes are minimal in the client code. This is very useful when constructing business entities which can be used in multiple places throughout an application. Say for example a business entity is used in 50 places within an application. Due to some new enhancement the constructor parameters needs to be changed. Adding or removing the constructor parameter will impact all those 50 places. We can minimise this change by using factory and centralising the object creation logic within the factory. By just changing the implementation within the factory we can ensure that all the client requests are satisfied.

While I was working with Tesco, our team had made good use of Factory pattern on almost all the projects that I was involved in. The factories were also helpful during unit testing as they allowed us to return mock instances of the classes.

As always the complete working solution is available for download.

Until next time Happy Programming.

Further Reading

Here are some book I recommend related to the topics discussed in this blog post.

spacer

Strategy Design Pattern

Design patterns are reusable solutions to repetitive problems. On various occasions I have seen people writing conditional code. Design patterns help in modularizing the code and making it extensible and maintainable. This post is about how we can refactor conditional logic to better maintainable and cleaner solution using Strategy Design Pattern.

Problem statement

Imagine we have to calculate the monthly instalment for a loan. The loan can be of various types for e.g. home loan, car loan, personal loan etc. Each loan can have different duration and also different interest rates. Based on these factors the equated monthly instalments (EMI) will be different. Lets look at a solution without using design patterns and try and refactor the same to one using design patterns.

For this hypothetical example lets consider that the interest rates for home loan is 10% and car loan is 8%. So we can start building the code to compute the EMI. Lets assume that in both the car and home loan cases the amount is same 100000 and the duration is 24 months. I’ll start by building a set of tests which is easier to get started as I don’t intend to build any user interface for this demo.

So here are couple of tests I have at this moment

    [TestClass]

    public class CalculatorTest

    {

        private Loan _loan;

 

        private Calculator _calculator;

 

        [TestInitialize]

        public void Setup()

        {

            _loan = new Loan

            {

                LoanAmount = 100000,

                DurationInMonths = 24,

            };

 

            _calculator = new Calculator();

        }

 

        [TestMethod]

        public void CalculateEMI_ForHomeLoan()

        {

            _loan.LoanType = LoanType.Home;

 

            decimal expectedInstallment = 4582.6m;

 

            decimal installmentAmount = _calculator.CalculateEMI(_loan);

 

            Assert.AreEqual(expectedInstallment, installmentAmount);

        }

 

        [TestMethod]

        public void CalculateEMI_ForCarLoan()

        {

            _loan.LoanType = LoanType.Car;

 

            decimal expectedInstallment = 4499.28m;

 

            decimal installmentAmount = _calculator.CalculateEMI(_loan);

 

            Assert.AreEqual(expectedInstallment, installmentAmount);

        }

    }

The implementation is pretty straightforward and self explanatory. The Calculator class below processes the input to calculate the appropriate EMI.

    public class Calculator

    {

        private const int CarLoanInterestRate = 8;

 

        private const int HomeLoanInterestRate = 10;

 

        public decimal CalculateEMI(Loan loan)

        {

            int monthlyInstallment = loan.LoanAmount / loan.DurationInMonths;

 

            decimal interestAmount = 0m;

 

            if (loan.LoanType == LoanType.Home)

            {

                interestAmount = GetHomeLoanInterestAmount(monthlyInstallment);

            }

            else if (loan.LoanType == LoanType.Car)

            {

                interestAmount = GetCarLoanInterestAmount(monthlyInstallment);

            }

 

            return monthlyInstallment + interestAmount;

        }

 

        private decimal GetCarLoanInterestAmount(int monthlyInstallment)

        {

            return monthlyInstallment * (CarLoanInterestRate / 100m);

        }

 

        private decimal GetHomeLoanInterestAmount(int monthlyInstallment)

        {

            return monthlyInstallment * (HomeLoanInterestRate / 100m);

        }

    }

 

Problem with this approach

On the first attempt this does look fine. The tests are green and the code also has all the ingredients. If we look carefully there are multiple code smells in the above code. Firstly the code violates the Single Responsibility Principle (SRP) principle. The SRP states that there should only be one reason for a class to change. But in the above class there are multiple reasons the class can change. It could change if the interest rate changes. The class will need to be changed if there is change in loan types etc.

Secondly, it poses a big challenge for maintainability and extensibility. If we are to calculate the EMI for personal loan we need to add another method to calculate the EMI for personal loan. This will have to be repeated for each new type of loan for which we need to calculate the EMI. So in this respect there is another principle which is violated and that is the Open Closed Principle (OCP). The OCP says that classes should be open for extension but closed for modification. This means that we need to encapsulate what varies. In our case the mechanism for calculating the EMI is variable. Lets look at how we can fix this problem.

Refactored solution

While refactoring code which is conditional like we have in this example, we can make use of the Strategy Pattern. We can define a strategy for calculating the interest amount. Based on the type of the loan we can call the appropriate strategy. Lets get started with defining a very simple interface for the strategy called IInterestCalculatorStrategy.

    public interface IInterestCalculatorStrategy

    {

        decimal CalculateInterestAmount(decimal monthlyInstallment);

    }

The interface is very simple and has only one method named CalculateInterestAmount. Lets implement the interest on the home loan. We’ll create a strategy called HomeLoanInterestCalculator which implements the IInterestCalculatorStrategy as shown below

    public class HomeLoanInterestCalculatorStrategy : IInterestCalculatorStrategy

    {

        private const int HomeLoanInterestRate = 10;

 

        public decimal CalculateInterestAmount(decimal monthlyInstallment)

        {

            return monthlyInstallment * (HomeLoanInterestRate / 100m);

        }

    }

Similarly we implement the CarLoanInterestCalculatorStrategy as

    public class CarLoanInterestCalculatorStrategy : IInterestCalculatorStrategy

    {

        private const int CarLoanInterestRate = 8;

 

        public decimal CalculateInterestAmount(decimal monthlyInstallment)

        {

            return monthlyInstallment * (CarLoanInterestRate / 100m);

        }

    }

Both the class implementations are exactly same as what was implemented in the solution without strategy as part of the respective methods. But the difference is that the strategies are lot more focussed on individual loan types and are a good way to organize code using SRP. With the strategies in place we refactor the calculator class to make use of one of these strategies.

Here is the refactored calculator class implementation.

    public class Calculator

    {

        public decimal CalculateEMI(Loan loan)

        {

            int monthlyInstallment = loan.LoanAmount / loan.DurationInMonths;

 

            IInterestCalculatorStrategy calculatorStrategy = CalculatorStrategyFactory.GetStrategy(loan.LoanType);

 

            decimal interestAmount = calculatorStrategy.CalculateInterestAmount(monthlyInstallment);

 

            return monthlyInstallment + interestAmount;

        }

    }

I have also made use of the Factory pattern in this case. I’ll cover factory pattern in a dedicated post in future. [Update : You can find out more about factory pattern  in the related post]. In the context of the current post, it is used to return an instance of the appropriate loan interest calculator strategy based on the type of loan.

The advantage of using the Strategy Pattern is that we can add any number of loan types in future and the Calculator class will work as expected without any changes. This refactoring has ensured that we followed the OCP by making the Calculator class closed for modification. Since we can add any number of loan types the class remain open for further extension. With addition of another strategy we can get the interest calculated without any change to the Calculator class.

So lets experiment a bit with this approach. Lets say we want to calculate the monthly instalment for Personal loan. The interest rate for personal loan is 15%. So lets add an implementation as PersonalLoanInterestCalculatorStrategy.

    public class PersonalLoanInterestCalculatorStrategy : IInterestCalculatorStrategy

    {

        private const int PersonalLoanInterestRate = 15;

 

        public decimal CalculateInterestAmount(decimal monthlyInstallment)

        {

            return monthlyInstallment * (PersonalLoanInterestRate / 100m);

        }

    }

We add a case to the factory to return the new strategy and that is it. There is no need to change anything in the calculator class.

Conclusion

When we have lengthy conditional code blocks it can be difficult to maintain and add new features. Factoring the code properly allows us to make changes easily without impacting existing functionality. Strategy pattern is one of the simplest and easiest to understand and implement. It helps to eliminate the conditional logic and makes the algorithms to be used interchangeably. By refactoring the existing code towards Strategy Pattern we can also ensure that we are programming to an interface and not to a concrete implementation. The Calculator class is completely decoupled from the interest calculation concrete implementation.

The classes are also lot more cleaner and concise. The respective constants related the interest rates are defined in respective strategies. Although the scope of this post is very small I hope it is helpful in demonstrating the intention behind it. The strategy pattern is an ideal refactoring pattern when there are multiple algorithms and they can be used interchangeably. 

We can look at the code quality metrics to see if this refactoring will be helpful. I ran the code metrics on the solution. In the first version without the strategy pattern, the CalculateEMI method was having the maintainability index of 63. In the refactored solution the same method is having the maintainability index of 70. We can always argue that this is not a huge gain. But my point is that for such a simple solution it might be minuscule but in real projects it is definitely much more than this. 

As always I have uploaded the complete working solution to DropBox.

Until next time Happy Programming Smile

Resources & further reading

I would recommend following resources for learning more about design patterns:

Do factory - http://www.dofactory.com/Patterns/Patterns.aspx

Refactoring to Patterns - http://industriallogic.com/xp/refactoring/

 

spacer