12

Why does this ShapeFactory use conditional statements to determine what object to instantiate. Dont we have to modify ShapeFactory if we want to add other classes in the future? Why doesnt this violate the open closed principle?

Factory Pattern Design

ShapeFactory Design

  • 2
    Which “factory pattern” are you referring to precisely? In general, a factory is any object or method that serves to instantiate an object. Then there are specific variations of this general idea such as the Abstract Factory Pattern, where each factory instance represents a specific palette of choices – usually managed via subclassing rather than conditionals. – amon Nov 17 '15 at 10:34
  • 3
    Thanks for that info, this clears up a lot. That is definitively an example of a factory pattern, but not of the Abstract Factory Pattern commonly associated with factory patterns. The code in that article is quite questionable, and I would not expect to see anything like that in real code. – amon Nov 17 '15 at 18:38
  • @ArmonSafai: You're linking this blog post a lot, but you're not really explaining why. Are we all somehow ignorant of the pattern? We have Google too, just like you. – Robert Harvey Nov 17 '15 at 19:00
  • 1
    @RobertHarvey I am linking this blog post to show how the factory pattern in that page is using conditionals – Armon Safai Nov 17 '15 at 19:53
18

The conventional object-oriented wisdom is to avoid if statements and replace them with dynamic dispatch of overridden methods in subclasses of an abstract class. So far, so good.

But the point of the factory pattern is to relieve you from having to know about the individual subclasses and work only with the abstract superclass. The idea is that the factory knows better than you which specific class to instantiate, and you will be better off working only with the methods publishd by the super class. This is often true and a valuable pattern.

Therefore, there is no way that writing a factory class can forego the if statements. It would shift the burden of choosing a specific class to the caller, which is exactly what the pattern is supposed to avoid. Not all principles are absolute (in fact, no principle is absolute), and if you use this pattern you'd assume that the benefit from it is greater than the benefit of not using an if.

  • 1
    It is perfectly possible to create a factory pattern without lots of ifs. See @BЈовић's answer for a simple example of how to achieve this. Downvoted. – David Arno Nov 17 '15 at 10:40
  • 11
    @DavidArno Naturally, there are different ways to choose the concrete class. Service Locator is one, a configurable IoC Container is another. Those are just implementation details; they don't detract from Killian's main message, which is that the Factory relieves the caller from having to decide which concrete class to instantiate. Don't get mired in the details. – Robert Harvey Nov 17 '15 at 18:53
  • I think there is a "better" way to implement the factory method pattern AND obeying to a certain extent the open/close principle. The idea I have is derived from the "extensible enums" proposed by Joshua Bloch in his book: "Effective Java." – hfontanez 6 hours ago
3

The example probably uses a conditional statement because it is the simplest. A more complex implementation might use a map or configuration or (if you want to be really fancy) some kind of registry where the classes can register themselves. However there is nothing wrong with using a conditional if the number of classes is small and changes infrequently.

Extending the conditional to add support for a new subclass in the future would indeed strictly speaking be a violation of the open/closed principle. The "correct" solution would be to create a new factory with the same interface. That said, adherence to the O/C principle should always be weighed against other design principles like KISS and YAGNI.

That said, the code displayed is clearly example code which is designed to show the concept of a factory and nothing else. E.g. it is really bad style to return null as the example does, but more elaborate error handling would just obscure the point. Example code is not production quality code, any you shouldn't expect it to be.

0

If you're talking about the Abstract Factory pattern, the decision making often isn't in the Factory itself but in application code. It's that code that chooses what concrete factory to instantiate and pass around to the client code that will use objects produced by the Factory. See the end of the Java example here : https://en.wikipedia.org/wiki/Abstract_factory_pattern

Decision making not necessarily implies if statements. It could read the concrete Factory type from a config file, derive it from a map structure, etc.

  • If I, the caller, am making the decision which concrete class to instantiate, then why am I bothering with an Abstract Factory? – Robert Harvey Nov 17 '15 at 19:00
  • Please define "the caller". As I describe in my answer, there is the global application code and then there's the code that needs to spawn objects using a Factory. While the latter indeed needs to be unaware of the concrete class to instantiate, some other contextual code has to know about it and new it up... – guillaume31 Nov 18 '15 at 8:30
0

If you think about the Open-Close at class level with this factory you are making other class in your system Open-Close, for example if you have other class that take one Shape and calculate the area (typical example) this class is OpenClose because it can calculate the area for new types of shapes without modification. Then you have another class that draws the shape, another class that take N shapes and return the bigger one and you can think in general that the other classes in your system that deals with shapes are Open-Close (at least about shapes). Looking at the design the factory enables the rest of the system to be Open-Close and off course the factory itself ITS NOT Open-Close.

Off course you can make this factory open-close too, via some kind of dynamic loading and your entire system can be Open-Close (you can add new shapes dropping some jar in the classpath for example). You need to evaluate is this extra complexity is worth depending on the system your are building, not all systems need pluggable features and not all the system need to be completely Open-Close.

0

The pattern itself doesn't violate the Open/Closed Principle (OCP). However, we violate the OCP when we use the pattern incorrectly.

The simple answer to this question is as follows:

  1. Create your base functionality using Factory Method Pattern.
  2. EXTEND your functionality by using the Abstract Factory Pattern

In the provided example, your base functionality supports three shapes: Circle, Rectangle, and Square. Suppose you need to support Triangle, Pentagon, and Hexagon in the future. To do this WITHOUT violating OCP, you must create an additional factory to support your new shapes (let's called AdvancedShapeFactory) and then use AbstractFactory to decide what factory you need to create in order to create whatever shapes you need.

New contributor
hfontanez is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
-1

It all depends how you implement it. You can use std::map to hold function pointers to functions creating objects. Then the open/close principle is not violated. Or switch/case.

Anyway, if you do not like the factory pattern, you can always use dependency injection.

  • 5
    How is switch/case better than conditionals? Using a map/dict/table to represent code as data is good, if you actually need a registry of different implementations – e.g. in some DI container implementations. But having different callbacks of the same type is not necessary for most factories! I don't quite get why you are suggesting that. Also, many DI containers are implemented in terms of factory objects, so suggesting to use DI instead of factories seems a bit circular. – amon Nov 17 '15 at 11:23
  • 1
    @amon I meant to use other types of DI - not the factory. – BЈовић Nov 17 '15 at 12:34
  • 1
    How's your factory going to decide which pointer to use? Eventually you have to make a decision. – whatsisname Nov 18 '15 at 5:11
  • @ArmonSafai ??? – BЈовић Nov 18 '15 at 6:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.