Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Make Your Java Factories Beautiful

DZone's Guide to

Make Your Java Factories Beautiful

If you're a Java programmer, you probably are at least familiar with the Factory Pattern. It's a great method for reducing coupling. Here's hot to make your Java Factories beautiful, a necessity when using large systems.

· Java Zone
Free Resource

Bitbucket is for the code that takes us to Mars, decodes the human genome, or drives your next car. What will your code do? Get started with Bitbucket today, it's free.

Make Your Java Factories Beautiful

Every Java programmer worth the name knows about the Factory Pattern. It is a convenient and standardized way to reduce coupling by teaching a component how to fish rather than giving it to them. When working with large systems, the pattern does, however, add a lot of boilerplate code to the system. For every entity, you need a number of different factories for producing different implementations of that entity, which is both tiresome and unnecessary to write.

Here is a typical example where you want a car trader to be able to create instances of the Car interface without knowing the exact implementation.

Car.java

public abstract class Car {
    private final Color color;

    public interface Factory {
        Car make(Color color);
    }

    protected Car(Color color) {
        this.color = color;
    }

    public abstract String getModel();
    public abstract int getPrice();
}

Volvo.java

public final class Volvo extends Car {
    public Volvo(Color color) {
        super(color);
    }

    public String getModel() { return "Volvo"; }
    public int getPrice() { return 10_000; } // USD
}

Tesla.java

public final class Tesla extends Car {
    public Tesla(Color color) {
        super(color);
    }

    public String getModel() { return "Tesla"; }
    public int getPrice() { return 86_000; } // USD
}

VolvoFactory.java

public final class VolvoFactory implements Car.Factory {
    public Car make(Color color) { return new Volvo(color); }
}

TeslaFactory.java

public final class TeslaFactory implements Car.Factory {
    public Car make(Color color) { return new Tesla(color); }
}

CarTrader.java

public final class CarTrader {

    private Car.Factory factory;
    private int cash;

    public void setSupplier(Car.Factory factory) {
        this.factory = factory;
    }

    public Car buyCar(Color color) {
        final Car car = factory.make(color);
        cash += car.getPrice();
        return car;
    }
}

Main.java

    ...
        final CarTrader trader = new CarTrader();
        trader.setSupplier(new VolvoFactory());
        final Car a = trader.buyCar(Color.BLACK);
        final Car b = trader.buyCar(Color.RED);
        trader.setSupplier(new TeslaFactory());
        final Car c = trader.buyCar(Color.WHITE);
    ...

One thing you might not have noticed yet is that most of these components are redundant from Java 8 and up. Since the factory interface might be considered a @FunctionalInterface we don’t need the factories, we can simply specify the constructor of the implementing classes as a method reference!

Car.java

public abstract class Car {
    private final Color color;

    @FunctionalInterface
    public interface Factory {
        Car make(Color color);
    }
}

Main.java

    ...
        trader.setSupplier(Volvo::new);
        trader.setSupplier(Tesla::new);
    ...

Notice that no changes are needed to the implementing classes Volvo and Tesla. Both the factories can now be removed and you are left with a much more concrete system!

(For simple examples such as this, the Factory interface is not needed at all. You could just as well make CarTrader take a Function<Color, Car>. The advantage of specifying an interface for the factory is that it is both easier to understand and it allows you to change the parameters of the constructor without changing the code that uses the factory).

Bitbucket is the Git solution for professional teams who code with a purpose, not just as a hobby. Get started today, it's free.

Topics:
lambda ,stream ,design ,api ,java 8 ,java

Published at DZone with permission of Emil Forslund, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}