Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the Factory Method pattern violate the Open/Closed principle?

Does the Factory Method pattern (not to be confused with the Factory or Abstract Factory patterns) violate the Open/Closed principle?

Update: To clarify, I'm referring to the scenario where a concrete class has static factory methods on it. For example (this is from the Wikipedia page on FMP):

class Complex 
{
    public static Complex fromCartesian(double real, double imag) {
        return new Complex(real, imag);
    }

    public static Complex fromPolar(double modulus, double angle) {
        return new Complex(modulus * cos(angle), modulus * sin(angle));
    }

    private Complex(double a, double b) {
       //...
    }
}

Doesn't the private constructor prevent the class from being subclassed, i.e. extended?

Wouldn't the class have to be modified to support new factory methods? For example, if the class initially only had fromCartesian and later fromPolar was needed, didn't the class have to be modified to support this?

Don't both of these violate Open/Closed?

like image 665
Todd Ropog Avatar asked Feb 04 '23 05:02

Todd Ropog


2 Answers

No, it doesn't violate the Open/Closed principle at all.

Open/Closed means you can modify the way a system works without modifying the code that already exists. You can extend the code and use it in different ways, but the old code is still in tact and doesn't need to be re-tested.

The Factory Method pattern will create a different type of object based on specified parameters. Factory Method actually works well with the Open/Closed principle if done correctly. However, if you create a new class and then want the Factory Method to create a new object of that type you would have to change the Factory Method.

Although, if you had some kind of configuration file or something of that sort that is read in by the Factory Method then you wouldn't have to change the Factory Method ... just the config file that then dictates what object will be created by the Factory Method.

like image 98
Brian T Hannan Avatar answered Mar 02 '23 01:03

Brian T Hannan


The Factory pattern isn't inherently a violator of OCP.

It depends on how you take the behavior of Complex further.

If Complex is required to support the production of new types of Complex object, and you choose to modify Complex by adding new fromX methods are added to support them, then this means that Complex becomes a violator of the OCP because Complex must be re-opened for modification:

class Complex 
{
    public static Complex fromCartesian(double real, double imag) {
        return new Complex(real, imag);
    }

    public static Complex fromPolar(double modulus, double angle) {
        return new Complex(modulus * cos(angle), modulus * sin(angle));
    }

    //class opened for modification
    public static Complex fromOtherMeans(String x , String y) {
        return new Complex(x, y);
    }
}

You could push this problem down into a text file or properties file of some sort in order to absolve yourself of having to change the java class, but it doesn't prevent you from having to write extra logic in this area of the solution in order to support new types of Complex.

Depending on the usage of Complex in your design (how are the various types different? How are you using them?), there are some alternative options which may apply well.

One such OCP friendly alternative is to subclass Complex to provide the additional factory methods. A subclass is the simplest illustration of how Complex is extended but not modified.

Another OCP friendly alternative to altering Complex in this case is the Decorator pattern. Continuously decorating Complex with the ability to create new variants of Complex respects the OCP because Complex is not modified but is extended by wrapping it with new functionality.

A third alternative might be to alter the structure of Complex so that its calculation is supplied by composition. This would open up to you the opportunity to use the Strategy pattern to diferentiate between the different behaviours of Complex.

The thing about the Factory pattern is that it helps context code respect OCP. One might employ one of the techniques above in order to stay on the right side of the OCP with their Factory class, but your colleagues are likely to take one look at the object graph, question the wisdom of having an object graph over a single Factory, and simplify it back into one Factory, which brings you back to to the first example.

In such cases, rather than trying to bend your implementation of the Factory pattern to respect the SOLID principles, consider why you're using it at all.

like image 36
8bitjunkie Avatar answered Mar 01 '23 23:03

8bitjunkie