Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace conditional with polymorphism

Tags:

I am trying to understand this clean code practice with an example. Consider a class Product having switch case for discount. I am trying to replace switch statement with polymorphism.

Before code:

class Product {     String priceCode;     int discount;      Product(String priceCode) {         setDiscount(priceCode);     }      public int getDiscount() {         return discount;     }      public void setDiscount(String priceCode) {         switch (priceCode) {             case "CODE1":                 discount = // some logic;             case "CODE2":                 discount = // some other logic;             case "CODE3":                 discount = // some other logic;         }     } } 

In below code as you can see I removed switch statement but I still have if conditions to create an object of discountStrategy. My question is I still have if conditions which I am trying to remove with Polymorphism.

After code:

class Product {     String priceCode;     DiscountStrategy discountStrategy;      Product(String priceCode) {         setDiscount(priceCode);     }      public int getDiscount() {         return discountStrategy.getDiscount();     }      public void setDiscount(String priceCode) {         if (priceCode.equals("CODE1")) {             discountStrategy = new DiscountStrategy1();         } else if (priceCode.equals("CODE2")) {             discountStrategy = new DiscountStrategy2();         }         // ...     } }  interface DiscountStrategy {     public int getDiscount(); }  class DiscountStrategy1 implements DiscountStrategy {     public int getDiscount() {         // calculate & return discount;     } }  class DiscountStrategy2 implements DiscountStrategy {     public int getDiscount() {         // calculate & return discount;     } }  class DiscountStrategy3 implements DiscountStrategy {     public int getDiscount() {         // calculate & return discount;     } } 

Can you please help me understand this concept with better implementation of this example?

like image 890
user1298426 Avatar asked Jan 22 '18 08:01

user1298426


People also ask

What is Replace conditional with polymorphism?

Replacing a switch statement directly with polymorphism would work, if the conditional was based on the Type of the object, which you simply overcome by using the Type of the interface.

What is one benefit of replacing conditionals with polymorphism?

Benefits. This technique adheres to the Tell-Don't-Ask principle: instead of asking an object about its state and then performing actions based on this, it's much easier to simply tell the object what it needs to do and let it decide for itself how to do that. Removes duplicate code.

Why polymorphism to if else or switch case is preferable?

Polymorphism will break your complex class into several smaller simpler classes which clearly define which pieces of the code are related and execute together. This helps testing since simpler/smaller class is easier to test.


1 Answers

I think that Product class must not be aware about the discount creation process, it should only use a discount. So, my suggestion is to create a discount factory with a Map that will hold different discount implementations:

class DiscountFactory {     private static final Map<String, DiscountStrategy> strategies = new HashMap<>();     private static final DiscountStrategy DEFAULT_STRATEGY = () -> 0;      static {         strategies.put("code1", () -> 10);         strategies.put("code2", () -> 20);     }      public DiscountStrategy getDiscountStrategy(String priceCode) {         if (!strategies.containsKey(priceCode)) {             return DEFAULT_STRATEGY;         }         return strategies.get(priceCode);     } } 

After that, the Product class can be simplified:

class Product {     private DiscountStrategy discountStrategy;      Product(DiscountStrategy discountStrategy) {         this.discountStrategy = discountStrategy;     }      public int getDiscount() {         return discountStrategy.getDiscount();     } } 

Functional interface will allow you to create different implementations using lambda expressions:

interface DiscountStrategy {     int getDiscount(); } 

And finally, example of the use of a product together with discount:

DiscountFactory factory = new DiscountFactory(); Product product = new Product(factory.getDiscountStrategy("code1")); 
like image 68
Oleksandr Pyrohov Avatar answered Sep 18 '22 22:09

Oleksandr Pyrohov