Search code examples
javaif-statementstrategy-pattern

Get rid of if statements to improve code design


How can I improve the design of the code below:

class Foo {
   public Configuration configure() {
      return new Configuration().withPropertyA().withPropertyB();
   }
}

class Configuration{


   private boolean propertyA = false;
   private boolean propertyB = false;

   public Configuration withPropertyA() {
       this.propertyA = true;
       return this;
   }

    public Configuration withPropertyB() {
       this.propertyB = true;
       return this;
   }

   public boolean hasPropertyA() {
      return this.propertyA;
   }

   public boolean hasPropertyB() {
      return this.propertyB;
   }

   ...
}

class Client{

public void someMethod(Configuration config) {
   if (config.hasPropertyA() {
      doStuffA();
   }
   if (config.hasPropertyB() {
      doStuffB();
   }
   //...
}

}

I.e., the Configuration class holds some flags for the caller (Client) that tell to the caller which "things" need to be configured. The Client knows what to do for each of the flags if they are set. I want to get rid of the if statement in Client as well as of the concept of simply setting boolean flags in the Configuration instance. Can you suggest a more "generic" and object oriented approach to this?

kind regards


Solution

  • You may use the Strategy pattern. Each If becomes a Strategy, which implements doStuff, with its own logic. When a property (A, B...) is set, you add the strategy to the list. You simply need to loop on the strategies and execute them, without any ifs:

    public class Foo  {
        public Configuration configure() {
            return new Configuration().withPropertyA().withPropertyB();
        }
    }
    
    class Configuration {
        Set<StuffStrategy> strategies = new HashSet<StuffStrategy>();
    
        public Configuration withPropertyA() {
            strategies.add(new PropertyAStrategy());
            return this;
        }
    
        public Configuration withPropertyB() {
            strategies.add(new PropertyBStrategy());
            return this;
        }
    
        public void executeStrategies() {
            for (StuffStrategy strategy : strategies) {
                strategy.doStuff();
            }
        }
    }
    
    interface StuffStrategy {
        public void doStuff();
    }
    class PropertyAStrategy implements StuffStrategy {
        @Override
        public void doStuff() {
        }
    }
    
    class PropertyBStrategy implements StuffStrategy {
        @Override
        public void doStuff() {
        }
    }
    
    class Client {
        public void someMethod(Configuration config) {
            config.executeStrategies();
        }
    }