DEV Community

Cover image for Static Factories: When Static Methods Shine (And Why They're Not Always Evil)
Cassio Menezes
Cassio Menezes

Posted on

Static Factories: When Static Methods Shine (And Why They're Not Always Evil)

In my recent article (Static X OOP), I suggested that regular classes and interfaces are more effective than utility classes' static methods, particularly when it comes to validation. There are distinctions, though, much like with other software development tasks. I want to look at a situation today where static methods—more especially, static factory methods—can be a useful and sophisticated tool. Inspired by Joshua Bloch's 'Effective Java,' let's see how I utilize them to improve the testability and flexibility of my code.

The Right Tool

'Effective Java' teaches us to strategically employ static factory methods instead of constructors when applicable. The ability to retrieve subtypes, give descriptive names, and manage instance generation are just a few benefits of these methods. They've been especially helpful to me in managing dependencies like the JapeContext in my work extending ERP platforms.

    public static BlockRepository getInstance() {
        return new BlockRepositoryImpl(new BlockRepositorySqlExecutorImpl(() -> {
            try {
                return JapeUtils.executeWithJape(context -> context); // Get JapeContext
            } catch (SQLException e) {
                throw new RuntimeException("Error getting JapeContext", e); // Handle exception
            }
        }));
    }
Enter fullscreen mode Exit fullscreen mode

In this case, BlockRepositoryImpl instances are created using a controlled entry point provided by the getInstance() method, which functions as a static factory. Using this method enables me to incorporate the intricate reasoning involved in acquiring the JapeContext into the factory method. Using a BlockRepositorySqlExecutorImpl and a lambda function, I can postpone retrieving the context until it's truly required. This type of deferred initialization can boost efficiency.

But the real magic happens when it comes to testing. By using a static factory, I can easily provide a mock JapeContext during unit tests. For instance, I can create a test-specific getInstance() method that returns a BlockRepositoryImpl instance with a mocked BlockRepositorySqlExecutorImpl. This allows me to isolate the BlockRepositoryImpl and test its behavior without relying on the actual ERP platform.

The flexibility of the code is also improved by the use of this pattern. All I have to do is alter the getInstance() method if I ever need to change how the JapeContext is retrieved. BlockRepositoryImpl callers are not impacted. This is a powerful demonstration of the Open/Closed Principle.

Takeaway

Static factory methods provide an alternative to static utility classes, which frequently result in rigid and untestable code. They offer a flexible and controlled method for managing dependencies, improving testability, and creating instances. We may create code that is reliable and manageable by using the right tool for the right job.

Have you used static factory methods in your projects? What insights and experiences do you have? Leave a comment below with your opinions! Let's continue the discussion and learn from each other.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay