Writing

Java functional programming to leverage polymorphism

How to replace a switch and reduce complexity?

Summary

A factory that creates profiles from a string, admin, HR, anonymous, almost always starts with a switch. It works, then every new profile adds a case and the class’s complexity grows with the catalogue. This article shows how to leave that spiral in Java, in four steps.

The idea is to replace the switch with a map of functional interfaces. One Supplier per profile, fed by method references such as Admin::new, and creation becomes a lookup with a default profile when the key is missing. Adding or removing a profile no longer touches any branching logic: the complexity stays flat. When the constructor takes one argument, Function replaces Supplier; when it takes several, a small dedicated functional interface does the job.

The last step goes further: an enum that carries, for each constant, its creation function, and a lookup through valueOf that falls back to the anonymous profile when the name is unknown. It is the version I find the most elegant and the most efficient, and the companion repository keeps one branch per step to follow the reasoning.

The subject is small, the lesson is not: polymorphism and lambdas are first of all a way to remove conditions, and a class whose complexity does not move when the business grows is a class you can maintain.

Key ideas

  • A switch in a factory grows with every new type; the class’s complexity follows the catalogue.
  • A map of Supplier fed by method references replaces the switch, and complexity stops depending on the number of profiles.
  • Function for one argument, a dedicated functional interface for several: the same principle extends to parameterised constructors.
  • An enum that carries its own creation function, with valueOf and a default fallback, is the most elegant version.

Why I wrote this

To show a way out of the switch that every factory starts with, and whose complexity grows with each new type, using nothing more than Java’s functional interfaces and method references, up to the enum form, the most elegant of the four steps.

Companion repositories