views:

91

answers:

3

I'm trying to understand the factory design pattern.

I don't understand why it's good to have a middleman between the client and the product (object that the client wants).

example with no factory:

$mac = new Mac();

example with a factory:

$appleStore = new AppleStore();
$mac = $appleStore->getProduct('mac');

How does the factory pattern decouple the client from the product?

Could someone give an example of a future code change that will impact on example 1 negative, but positive in example 2 so I understand the importance of decoupling?

Thanks.

+2  A: 

Don't know if I can put it any better than IBM did https://www.ibm.com/developerworks/library/os-php-designptrns/#N10076

SeanJA
+4  A: 

I think it has to do with the resources needed to construct some types of objects.

Informally, if you told someone to build a Mac, it would be a painstaking process that would take years of design, development, manufacturing, and testing, and it might not be done right. This process would have to be repeated for every single Mac. However, if you introduce a factory, all the hard work can be done just once, then Macs can be produced more cheaply.

Now consider Joomla's factory.php. From what I can tell, the main purpose of JFactory is to pool objects and make sure objects that should be the same aren't copied. For instance, JFactory::getUser() will return a reference to one and only one object. If something gets changed in that user object, it will appear everywhere. Also, note that JFactory::getUser() returns a reference, not a new object. That is something you simply cannot do with a constructor.

Often, you need local context when constructing an object, and that context may persist and possibly take on many forms. For instance, there might be a MySQL database holding users. If User objects are created with a constructor, you'll need to pass a Database object to the constructor (or have it rely on a global variable). If you decide to switch your application to PostgreSQL, the semantics of the Database object may change, causing all uses of the constructor to need review. Global variables let us hide those details, and so do factories. Thus, a User factory would decouple the details of constructing User objects from places where User objects are needed.

When are factories helpful? When constructing an object involves background details. When are constructors better? When global variables suffice.

Joey Adams
+1 analogy bonus
SeanJA
but isnt this called "moving process to a central place". what i dont understand is the word decouple.
never_had_a_name
but if i need to change database and im using factory, i still have to change my code in the factory. it's this part i dont quite understand. either way i have to change, now i just moved it to another class, the factory. i can understand that this is good if dealing with frameworks/os applications. your users interacting with your code dont have to rewrite their code. but if im the only one that am using the code i write, how is factory better? i still have to change if i change database.
never_had_a_name
What's better? Changing a bunch of code in one place, or changing a bunch of code in a lot of places?
Joey Adams
@Joey Well... if you want to keep your job for a long time...
SeanJA
+1  A: 

This example returns an object of type Mac and it can never be anything different:

$mac = new Mac();

It can't be a subclass of Mac, not can it be a class that matches the interface of Mac.

Whereas the following example may return an object of type Mac or whatever other type the factory decides is appropriate.

$appleStore = new AppleStore();
$mac = $appleStore->getProduct('mac');

You might want a set of subclasses of Mac, each representing a different model of Mac. Then you write code in the factory to decide which of these subclasses to use. You can't do that with the new operator.

So a factory gives you more flexibility in object creation. Flexibility often goes hand in hand with decoupling.


Re your comment: I wouldn't say never use new. In fact, I do use new for the majority of simple object creation. But it has nothing to do with who is writing the client code. The factory pattern is for when you want an architecture that can choose the class to instantiate dynamically.

In your Apple Store example, you would probably want some simple code to instantiate a product and add it to a shopping cart. If you use new and you have different object types for each different product type, you'd have to write a huge case statement so you could make a new object of the appropriate type. Every time you add a product type, you'd have to update that case statement. And you might have several of these case statements in other parts of your application.

By using a factory, you would only have one place to update, that knows how to take a parameter and instantiate the right type of object. All places in your app would implicitly gain support for the new type, with no code changes needed. This is a win whether you're the sole developer or if you're on a team.

But again, you don't need a factory if you don't need to support a variety of subtypes. Just continue to use new in simple cases.

Bill Karwin
so the focus is on "how can i write code so whenever i change MY code, the CLIENT doesnt have to"? so basically i NEVER want the client to use new on the "end-products". i want to provide an abstraction layer (factory) for creation of products. so he doesnt have to know what happens behind the scenes? am i correct? but what about when i code everything myself? either way, i have to change. i dont quite understand where the focus lies or what i as a developer wants to do.
never_had_a_name