javaspringspring-bootdesign-patternsrule-engine

Determine the appropriate design pattern in Java/Spring


We have a method which contains a complex business logic to evaluate a lot of conditions and by the end this method should return an object of type Rule.

The method is implemented using a lot of if else with nested if else as well. The execution order is VERY IMPORTANT in our situation.

We want to refactor this method using a design pattern. I saw a lot of people on stackoverflow talking about Chain of Responsibility, Command, Factory and State Pattern but I'm not sure about the right pattern for this use case.


Solution

  • I've looked at doing something similar recently. I found the solution fell between the Visitor and Chain of Responsibility patterns. Neither provided a natural fit.

    I was able to compose a list of the objects that had to be given a chance to perform some business logic and return the final result. Each had a unique set of dependencies. I used an IoC container to resolve these objects using a common interface. I was able to order these by using a property that represented the sequence and sorting the list by this.

    The problem I had was that each object needed different runtime data. The Visitor and Chain of Responsibility patterns typically use a consistent method signature. I found I needed a 'context' object parameter to cover all the potential properties each logic object might need. This is when I knew it really the correct approach as many objects were being passed data they weren't interested in.

    Due to time constraints, I reverted to something similar to the Template Method pattern, but was just a Transaction Script really, where the method called each object following a defined sequence. Objects were resolved via IoC and had interfaces for some abstraction that supported automated testing. This was ok, but became tricky with tests as it required more mocking than it should.

    Ultimately, I think something like this doesn't have a neat, 'classic' design pattern that solves it. I think you're looking to refactor your business logic into individual classes and then call them via an iterator or pipeline? if you redefine your question highlighting that design problem rather than trying to find a pattern that fits, you might get a better answer.