Remove switch statements using polymorphism

“Two books on a desk near a MacBook with lines of code on its screen” by Émile Perron on Unsplash

In this post we will use polymorphism to remove switch statements. Inappropriately using switch statements is a sign of code smell. Robert Martin in his book Clean Code says that he limits himself to one switch statement per object type.

We will use example of a Customer class. Initially we will use switch statements to implement the methods of the class. Then we will use polymorphism to refactor it and improve the code structure.

Each Customer has a membership type. getMonthlyPrice method calculates the monthly membership cost of Customer based on their membership level. So far its all good. However we have been asked to add functionality to calculate points earned by the customer. Customers earn points based on their membership level and the amount they spent.

Now we can clearly see whats wrong with our approach. We have duplicated switch statements. Our example is really simple, but the real world application will have complex logic for these calculations.

The first thought to solve this would be to use inheritance and introduce BronzeCustomer, SilverCustomer and GoldCustomer which will extend abstract Customer. Each of these classes will implement their version of getMonthlyPrice and getPointsEarned. But inheritance will not work in our case as the membership level might change in runtime after the object creation. What I mean by this is a Customer can be upgraded or downgraded to other membership level anytime.

We can solve this problem by using State Pattern. We will begin refactoring by introducing Member interface and delegate the functionality of price and membership points calculation to it. We will then create BronzeMember, SilverMember and GoldMember which will implement Member interface.

Next we will update Customer class to use Member interface. We have introduced a private property member. Customer delegates the work of calculation to its member instance. When a membership is set, the member instance is also updated based on the membership type. The constructor is updated to use the setMembership method. This is how our final Customer class looks like.

We have successfully used polymorphism to refactor the switch statements in the Customer class. All the complex logic of calculating membership cost and points is delegated to respective classes. When a new membership level is added, we can simply update setMembership method to support it. Above all, none of the client classes using Customer will notice that the class has been changed and continue to work as before.

Originally published at subash.com.au on November 19, 2017.

Lead Software Engineer at A Cloud Guru