• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Factory Method issue from HeadFirst Design Patterns book

 
Ranch Hand
Posts: 51
Hibernate Spring Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all,

(I'm not sure whether this is the place to ask a Pattern question using an example in Head first book. But I couldn't find any active forums reserved for HFDP).

Following are two examples using SimpleFactory and Factory Method.

Simple Factory


Factory Method


In Factory Method, a subclass of PizzaStore decides how Pizzas created while in SimpleFactory, you have the ease of configuring which region's Pizzas are created just by changing the SimpleFacoty parameter for the constructor.

So what is the importance of having Factory Method? I can not understand why Simple Factory is not considered as a good design pattern while Factory Method is considered (even while it uses subclasses to do the work).

Even the creation and usage is separated well in Simple Factory.

Could you please discuss this a bit.

Thanks.
Kamal
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's simply a balance: Factory Method needs less code, Simple Factory (sounds to me like that's an Abstract Factory) is more flexible.

If you don't need the flexibility, and don't care about the closer coupling, Factory Method can simply be the less complex design.
 
Bartender
Posts: 2968
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Kamal Mettananda:
So what is the importance of having Factory Method? I can not understand why Simple Factory is not considered as a good design pattern while Factory Method is considered (even while it uses subclasses to do the work).



HFDP p.119:


But you'd like a little more quality control...
...
you see what you'd really like to do is create a framework that ties the store and pizza creation together[, enforce creation consistency], yet still allow things to remain flexible.



HFDP p.120:


There is a way to localize all the pizza making activities to the PizzaStore class and yet give the franchises freedom to to have their own regional style.



GoF Abstract Factory Consequences:


3. It promotes consistency among products. When product objects in a family are designed to work together, it's important that an application use objects from only one family at a time. AbstractFactory makes this easy to enforce.



Basically this is a shift in preparation to later consolidate all pizza making activities the PizzaIngredientFactory Abstract Factory.

A lot more is explained later in the chapter (it goes to p. 168).

Ultimately it is more important to comprehend/understand the design principles featured in HFDP than to memorize all of the patterns.

FYI: The support forum for HFDP can be found here at www.headfirstlabs.com � though questions from HFDP are sometimes discussed here.
 
Kamal Mettananda
Ranch Hand
Posts: 51
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks a lot for the feedback. But still I'm not fit with it, sorry I'm still learning these.


HFDP p.119:

quote:
But you'd like a little more quality control...
...
you see what you'd really like to do is create a framework that ties the store and pizza creation together[, enforce creation consistency], yet still allow things to remain flexible.



ties the store and pizza creation together[, enforce creation consistency] - How do we enforce this just by subclassing PizzaStore? All the methods like prepare(), cut() etc are implemented in Pizza implementations and PizzaStore just call those in the specified order. What can we enforce using a PizzaStore subclass which is not achievable using SimpleFactory?

HFDP p.120:

quote:
There is a way to localize all the pizza making activities to the PizzaStore class and yet give the franchises freedom to to have their own regional style.



But even when we use the SimpleFactory and PizzaStore, pizza making activities were inside PizzaStore. Also we provided the freedom to have their own regional style using subclasses of SimpleFactory which creates reginal specific pizzas.

So still I could not understand the difference between the Simple Factory vs Factory Method? Could you explain a bit more? I'm trying to understand the theory between those 2, but not clear yet.

Thanks in advance.
Kamal
 
Kamal Mettananda
Ranch Hand
Posts: 51
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


It's simply a balance: Factory Method needs less code



Factory Method needs less code, I'm not sure? Still it needs to have subclasses of PizzaStore to do the creational work where as subclasses of SimpleFactory does that in simple factory approach.


Simple Factory (sounds to me like that's an Abstract Factory) is more flexible.



What is the flexibility we achieved with Simple Factory? Could you explain?
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Factory Method is less complex, because clients don't need to create and assemble two objects as when using the factory. There is also one less class hierarchy.

Abstract Factory is more flexible because you can use inheritance only once, but can pass in as many factories as you like. You can also create the factory at a different place than the object the factory is used in. You could even exchange the factory as often as you want if you provide a setter for it.
 
Ranch Hand
Posts: 434
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Kamal, I think the sample you give is an Abstract Factory, not a Simple Factory. A Simple Factory is just a good practice to split what varies from others. It's usually a simple class, and not extending any other abstract factory.
 
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Kamal

If you read the text in page 119 you will find the explanation.

For SimpleFactory, the pizza creation code is written in different Factory, then the prepare, bake, cut, box will be different, that's the reason why the author said 'a little more quality control'.

In the next page a Template Method pattern is used to work with the Abstract Factory. Then for all the pizza store, only the creatpizza method is different since the toppings, dough, sauce are different.
 
Kamal Mettananda
Ranch Hand
Posts: 51
Hibernate Spring Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Ben Two:

For SimpleFactory, the pizza creation code is written in different Factory, then the prepare, bake, cut, box will be different, that's the reason why the author said 'a little more quality control'.



Hi Ben,
It's not clear. prepare, bake, cut and box methods are implemented inside each Pizza subclass, not in any other place. So how do we achieve quality by moving the creation code from SimpleFactory to a subclass of a Factory method class.

Kamal
 
Ben Two
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Kamal

Do you catch the meaning of Quality Control?

It does not mean the quality of your Factory Method design, it means the quality control of Pizza creation.

Every pizza factory has it's own style of boxing, cutting, etc. That's the point that the author want to use the same boxing , cutting, for all the factory. That is Quality Control. This is a business vocabulary, not software here.
 
Kamal Mettananda
Ranch Hand
Posts: 51
Hibernate Spring Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Ben Two:
Every pizza factory has it's own style of boxing, cutting, etc. That's the point that the author want to use the same boxing , cutting, for all the factory.



Hi Ben,

Did you read my reply?

prepare, bake, cut and box methods are implemented inside each Pizza subclass, not in any factory.



Which factory defines the prepare, bake, etc methods?
 
Ben Two
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Kamal

Ofcourse I read your reply.

Now I'd like to explain more on the difference between SimpleFactory and AbstractPizzaStore which is actually a Abstract Factory using Template Method.

with SimpleFactory, you can refer to Page 117
PizzaStore aggregate a SimplePizzaFactory, SimplePizzaFactory create and return an abstract class Pizza with prepare, bake ,cut, box operations, and CheesePizza, VeggiePizza extend the abstract Pizza, so they have their own prepare, bake ,cut, box which is different.

Before:

class NYSimpleFactory extends SimpleFactory
{
Pizza createPizza(String type){
//creates Newyork specific
Pizza pizza;
if (type.equals("cheese")) pizza=new NYStyleCheesePizza();

return pizza;
}}

class PizzaStore {
public PizzaStore(SimpleFactory factory)
{ .... }
Pizza orderPizza(String type)
{ Pizza pizza=factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}

After:

public abstract class PizzaStore
{
abstract Pizza createPizza(String type);
public Pizza OrderPizza(String type)
{
Pizza pizza=createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}


public class NYStylePizzaStore
public Pizza createPizza(String type)
{
if (type.equals("cheese")) return new NYStyleCheesePizza();
......
}

Now the biggest different of two solution is two class PizzaStore and SimpleFactory combined into one class, the Concrete PizzaStore.

Client invocation change from

SimplePizzaFactory factory=new NYStylePizzaFactory();
PizzaStore store=new PizzaStore(factory);
store.orderPizza("cheese");

into
PizzaStore store=new NYStylePizzaStore();
store.orderPizza("cheese");

If you read the second to the last paragragh of page 119
"Rethinking the problem a bit, you will see that what you'd really like to do is create a framework that ties the store and the pizza creation together, yet still allow things to remain flexible"

So in my opinion the only improvement is, No aggregation from PizzaStore to SimpleFactory is needed. In a word, 2 in 1.
And for the quality control, Let's assume every PizzaStore has their code fragment of cutting, baking ,etc. The evidence is the first paragragh in page 119
"the franchises are were using your factory to create pizza, but start to employ their own procedure for the rest of the process, bake differently, cut differently, use different box"
 
Kamal Mettananda
Ranch Hand
Posts: 51
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ben,

Thanks for keeping up with the discussion. I like to move it further to understand things more clearly.


So in my opinion the only improvement is, No aggregation from PizzaStore to SimpleFactory is needed. In a word, 2 in 1.



Can we consider aggregating two operations like "creation (create method)" and "process (prepare, cut etc methods)" into one class as an improvement?


"the franchises are were using your factory to create pizza, but start to employ their own procedure for the rest of the process, bake differently, cut differently, use different box"



Even though that sentence says so;
how can different simple factories employ their own procedures for the rest of the process as all the methods like prepare, cut etc are defined in Pizza implementations and called by PizzaStore? Seems the above statement isn't valid?
[ November 29, 2007: Message edited by: Kamal Mettananda ]
 
Peer Reynders
Bartender
Posts: 2968
6
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Kamal Mettananda:
Seems the above statement isn't valid?



The SimplePizzaFactory deals only with one class of objects: Pizza. How that Pizza is composed is anybody's guess because there are no further constraints.

The PizzaIngredientFactory controls what ingredients are used in the process of Pizza preparation which is equated with improved quality control.

In the case of the SimplePizzaFactory the factory loses control after the Pizza instance is created - the Pizza instance could do whatever it wanted during the prepare, bake, cut, box methods.

In the case of the PizzaIngredientFactory some of that control is delegated to the factory. For example during "prepare" the factory supplies the approved ingredients for the pizza. So there is a clearer division of responsibilities between the Pizza and the Factory. For example the Cheese pizza decides that it requires dough, sauce, and cheese (no veggies, pepperoni, or clams) for the prepare step. The factory on the other hand decides which dough, sauce, and cheese are used (but it can't force any veggies, pepperoni or clams on the Pizza because the Pizza would have to request them first).
 
Kamal Mettananda
Ranch Hand
Posts: 51
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Peer,

I have no issue regarding the Ingrediant factory use, and I know that it controls the ingrediant's creation.

So what is the importance of having Factory Method? I can not understand why Simple Factory is not considered as a good design pattern while Factory Method is considered (even while it uses subclasses to do the work).

Even the creation and usage is separated well in Simple Factory.



As I mentioned in my first post in this thread, I'm looking for why the Simple Factory is not considered better than Factory method in that example.

Could you elaborate that?
 
Ben Two
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Kamal Mettananda:
Can we consider aggregating two operations like "creation (create method)" and "process (prepare, cut etc methods)" into one class as an improvement?



Hi Kamel,

If you consider this improvement, then there is no real difference. But since SimpleFactory did seperate create and process. It's a worse design since every subclass of SimpleFactory implement their own process which lose quality control

regards
Ben
 
Kamal Mettananda
Ranch Hand
Posts: 51
Hibernate Spring Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ben,


It's a worse design since every subclass of SimpleFactory implement their own process which lose quality control

.

No way, Simple Factory does not implement any process, it's rather a factory that creates Pizza objects, not a place where a process is implemented.
 
Ben Two
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Kamal

First, if you insist SimleFactory only handle create not process, then it lose the quality control, please refer to the above code I attached, Every PizzaStore has their own process.

Second, if you want to put the create and process together as an improvement which you put forward above. Then there is no real difference.
 
Ben Two
Ranch Hand
Posts: 35
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, I made a mistake by saying "Each subclass of SimleFactory implement their own process", it should be

Each PizzaStore aggregated with a SimpleFactory implement their own process

class PizzaStore {

public PizzaStore(SimpleFactory factory)
{ .... }
Pizza orderPizza(String type)
{ Pizza pizza=factory.createPizza(type);
prepare(pizza);
bake(pizza);
cut(pizza;
box(pizza);
return pizza;
}
}

The detail of the orderPizza method does not appear in the book but you can assume this from the paragraph in that page.
 
Kamal Mettananda
Ranch Hand
Posts: 51
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Pizza orderPizza(String type)
{ Pizza pizza=factory.createPizza(type);
prepare(pizza);
bake(pizza);
cut(pizza;
box(pizza);
return pizza;
}



Please refer the book again. What you have written above is not what is in the book. Seems you have re-written that to explain what you said. See below for correct code.



PizzaStore class is not the class which defines the prepare(), bake etc method, it's the Pizza subclasses which does it.
 
Ben Two
Ranch Hand
Posts: 35
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Faint

" Let's assume every PizzaStore has their code fragment of cutting, baking ,etc. The evidence is the first paragragh in page 119"

What I've done is not to support my opinion, but put on more code for the PizzaStore working with SimpleFactory which support the words in the book.

If you don't agree me, could you please tell me why the author said we need more quality control?

PizzaStore is a concrete class with SimpleFactory

public PizzaStore
{
public PizzaStore(SimpleFactory factory)

public Pizza orderPizza(String type)
{
Pizza pizza;
pizza=factory.createPizza(type);
pizza.prepare(); // this line can be removed or replaced by various pizzastore, for example local method: prepare(pizza);
pizza.bake(); //this line can be removed or replaced by various pizzastore, for example local method: bake(pizza);
pizza.cut(); //this line can be removed or replaced by various pizzastore, for example local method: cut(pizza);
pizza.box();// this line can be removed or replaced by various pizzastore, for example local method: box(pizza);

}

}

From the above code, could you please tell me is it possible that different concrete pizzastore use different process(prepare, bake, cut, box)? If the answer is yes, then is it a worse solution since it lost quality control?

I'm afraid that is what I can say, if you don't agree I give up.
 
Peer Reynders
Bartender
Posts: 2968
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Kamal Mettananda:
I'm looking for why the Simple Factory is not considered better than Factory method in that example.



To be honest I don't think that there is a statement that one is in fact better than the other. Throughout the chapter more and more requirements are placed on the design, changing the design pressures. The simple factory did what it set out to do but then they changed the requirements and other measures needed to be taken to optimize the design so that it could "reach a new equilibrium".


Observation: Instantiation can lead to coupling problems (p.109)
Objective: Make sure that the stable part is "closed for modification" (p.111)
Objective: Identify the aspects that vary and separate them from what says the same (p.111)
Observation: The menu keeps changing. (p.113)
Goal: Contain/encapsulate the aspect under pressure to change in its own class. (p.113)

Solution (p.116):
  • PizzaStore (STABLE) - contains the stable aspects of the domain. It no longer has any direct dependencies on concrete Pizzas, only the general Pizza interface. Now has an additional dependency on SimplePizzaFactory. Observation: PizzaStore is tightly coupled to SimplePizzaFactory.
  • SimplePizzaFactory (VARIES) - contains the aspects of the domain that are likely to change.


  • Major change in the domain (business): Going from a store to a franchise. (p.118)
    New Objective #1: Accommodate regional variations/preferences to the PizzaStore (something new that varies) (p.118)

    Preliminary Solution (p.116):
  • NYPizzaFactory (VARIATION A) - injected into PizzaStore to make it behave like a "New York Pizza" Store.
  • ChicagoPizzaFactory (VARIATION B) - injected into PizzaStore to make it behave like a "Chicago Pizza" Store.

  • New Objective #2: Need additional controls on the pizza production process. Use only ingredients of approved origin (but leave the selection of the category of ingredients to the regional franchise), boxes of approved origin (that are strong, sog-resistent enough, have the appropriate advertising) while still maintaining control of the overall pizza making process (make sure that pizza's are properly baked and cut) (p.118).

    Observation: Currently there is no way a client can tell what PizzaStore it is dealing with. Many clients don't care because they like all sorts of Pizzas. However some clients are more picky - they absolutely love New York Pizzas but they can't stand those Deep Dish Chicago Pizzas. Now you could simply add a whatTypeAreYou method to the PizzaStore which is delegated to the PizzaFactory - however in object-oriented design you are always looking for reasonable opportunities to Replace Conditional Logic with Polymorphism.

    So instead of implementing the variation through two different PizzaFactories we are now implementing the same variation in two different PizzaStores:

    Preliminary Solution (p.120):
  • PizzaStore (STABLE, COMMONALITIES, ABSTRACT) - contains the common and stable aspects of the domain; every pizza will be created, prepared, baked, cut and boxed. While it requires that a pizza can be created it leaves the actual implementation of the creation process to the regional franchise - that is why it is using a template method (abstract createPizza(...); yes they snuck one in here even though that isn't covered until p.275). Client's who don't care about the type of Pizzas they get can simply deal with a PizzaStore - even though the concrete store is either a NYPizzaStore or ChicagoPizzaStore. More discerning clients can make sure that they are only dealing with "their kind of store" and avoid the others.
  • NYPizzaStore (VARIATION A, CONCRETE) - This is the "New York Pizza" Store. It's super-class PizzaStore dictates that every ordered pizza has to be created, prepared, baked, cut and boxed. However it gets to create its own regional pizzas.
  • ChicagoPizzaStore (VARIATION B, CONCRETE) - This is the "Chicago Pizza" Store. Again the super-class imposes the steps in the Pizza making process (but not the implementations) while the ChicagoPizzaStore has the freedom (and responsibility) of implementing which Pizza's to make.


  • At this point you will probably still want to have a NYPizzaFactory for the NYPizzaStore, and ChicagoPizzaFactory for the ChicagoPizzaStore because you like the encapsulation of the creation process. However I already made the observation that the original PizzaStore was tightly coupled to the original SimplePizzaFactory. In that case it was OK because we wanted the separation between what is likely to change and what is likely to stay the same. Once we needed to use more than one Factory we needed to loosen the coupling between the PizzaStore and the PizzaFactories by introducing a PizzaFactory interface or by using SimplePizzaFactory as a super-class (considering the differences between the Factory implementations, an interface would make more sense; there just isn't enough common implementation between NYPizzaFactory and ChicagoPizzaFactory to justify a common base class).

    NYPizzaStore/NYPizzaFactory and ChicagoPizzaStore/ChicagoPizzaFactory would exhibit the same tight coupling and they have the same reasons for changing - changing the type of Pizzas that are offered. Introducing an interface would loosen the coupling but serve no purpose as we don't want to supply the stores with different PizzaFactories. Introducing the interface would make matters more complex for no apparent reason. Yes, it would be more flexible but it isn't the type flexibility that we need at this point. If you take a close look at XxxPizzaStore/XxxPizzaFactory you would detect a Lazy Class Smell. In this case that would suggest an Inline Class refactoring. So which one of the XxxPizzaStore/XxxPizzaFactory classes do we stick with? The XxxPizzaFactory cannot give us polymorphic behavior of the XxxPizzaStore - so it loses and all the functionality is implemented in XxxPizzaStore.

    Now that the factory is gone we introduce the PizzaIngredientFactory which has an entirely different purpose...satisfying "New Objective #2". If we had retained the PizzaFactories we would have to pass the PizzaIngredientFactory into the PizzaFactory so that the PizzaIngredientFactory could be handed to the Pizza; we simply don't gain enough at this point from this extra level of complexity.


    Notice how commonality vs. variability is used to justify certain design decisions?

    Design Patterns Explained 2e pp.231-232:

    You still have to fill in the rest by identifying relationships among the concepts in the problem domain. The method for this uses commonality and variability analysis (CVA). CVA is generally usable, whereas "thinking in patterns" typically is not. I start with "thinking in patterns" because it is an easier process to learn and gives insight into the more useful CVA.

     
    "How many licks ..." - I think all of this dog's research starts with these words. Tasty tiny ad:
    a bit of art, as a gift, the permaculture playing cards
    https://gardener-gift.com
    reply
      Bookmark Topic Watch Topic
    • New Topic