You are on page 1of 33

The Simple Factory Pattern and Factory Method Pattern

CSCI 3132 Summer 2011

1

New  is  an  implementa-on  
•  Calling  “new”  is  certainly  coding  to  an   implementa-on   •  In  fact,  it’s  always  related  to  a  concrete  class   •  (Open  for  Modifica-on)   •  That’s  fine  when  things  are  simple,  but  .  .  .  

2

Look  Out  For  Change  
•  When  you  have  several  related  classes,  that’s   probably  a  good  sign  that  they  might  change  in   the  future  
Duck duck;! if (picnic) {! ! duck = new MallardDuck();! } else if (hunting) {! ! duck = new DecoyDuck();! } else if (inBathTub) {! ! duck = new RubberDucky();! }! 3

  •  Thus.   •  Concrete  classes  are  oKen  instan-ated  in   more  than  one  place.   •  Such  extensions  can  result  in  updates  being   more  difficult  and  error-­‐prone.    Instan-a-ng  Concrete  Classes   •  Using  new  instan-ates  a  concrete  class.   •  This  is  programming  to  implementa-on   instead  of  interface.   4 .  when  changes  or  extensions  are  made   all  the  instan-a-ons  will  have  to  be  changed.

 namely.  the  sauce  used   and  the  toppings.Example   Suppose  that  you  are  required  to  develop  a   system  that  accepts  orders  for  pizzas.   5 .  The  pizzas  differ   according  to  the  dough  used.   Greek.  cheese.   Draw  a  class  diagram  for  the  system.  and  pepperoni.    There   are  three  types  of  pizzas.

! ! return pizza.Design  Principle   •  What  should  you  try  to  do  with  code  that   changes?   Pizza orderPizza() {! ! Pizza pizza = new Pizza().! pizza.! pizza.box().! pizza.bake().! }! 6 . ! ! ! ! ! pizza.prepare().cut().

! pizza.! }! pizza.box().! pizza.cut().! ! ! ! ! ! ! ! ! ! ! ! if (type.equals(“pepperoni”)) {! !pizza = new PepperoniPizza().prepare().equals(“cheese”)) {! !pizza = new CheesePizza().! pizza.! }! 7 .bake().equals(“greek”)) {! !pizza = new GreekPizza().! ! return pizza.! } else if (type.Pizza orderPizza(String type) {! ! Pizza pizza.! } else if (type.

Example:Class  Diagram   Problems  with  the  design   8 .

! }! ! pizza.cut().! ! pizza.Pizza orderPizza(String type) {! ! Pizza pizza.equals(“greek”)) {! !pizza = new GreekPizza().! ! pizza.! ! ! ! ! ! ! ! ! ! ! ! if (type.box().! ! pizza.bake().equals(“pepperoni”)) {! !pizza = new PepperoniPizza().! }! 9 .equals(“cheese”)) {! !pizza = new CheesePizza().prepare().! ! return pizza.! } else if (type.! } else if (type.equals(“sausage”)) {! !pizza = new SausagePizza().! } else if (type.! } else if (type.equals(“veggie”)) {! !pizza = new VeggiePizza().

equals(“veggie”)) {! !pizza = new VeggiePizza().! } else if (type.equals(“cheese”)) {! !pizza = new CheesePizza().cut().! } else if (type.bake().equals(“sausage”)) {! !pizza = new SausagePizza().! ! pizza.prepare().! ! pizza.! }! ! pizza.! } else if (type.equals(“pepperoni”)) {! !pizza = new PepperoniPizza().Pizza orderPizza(String type) {! ! Pizza pizza.equals(“greek”)) {! !pizza = new GreekPizza().! ! return pizza.! ! pizza.! }! Encapsulate! 10 .box().! } else if (type.! ! ! ! ! ! ! ! ! ! ! ! if (type.

Revised  System   •  Suppose  that  the  Greek  pizza  is  not  popular   and  must  be  removed  and  two    new  pizzas.   Clam  and  Veggie.   •  Crea-ng  a  SimpleFactory  to  encapsulate  the   code  that  changes  will  make  the  design  more   flexible.   •  Remove  the  code  that  creates  a  pizza  –  forms  a   factory.  must  be  added  to  the  menu.   11 .   •  Programming  to  implementa-on  like  makes   such  changes  difficult.

! ! }! }! Now orderPizza() is tidy 12 .equals(“pepperoni”)) {! ! pizza = new PepperoniPizza().equals(“sausage”)) {! ! pizza = new SausagePizza().! } else if (type.! } else if (type.equals(“veggie”)) {! ! pizza = new VeggiePizza().! } else if (type.equals(“cheese”)) {! ! pizza = new CheesePizza().! }! ! ! return pizza.public class SimplePizzaFactory {! ! public Pizza createPizza(String type) {! ! ! Pizza pizza.! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! if (type.

! pizza.! ! }! }! 13 .box().! ! ! ! ! ! ! ! ! pizza.createPizza(type).cute().! pizza.public class PizzaStore {! ! SimplePizzaFactory factory.! No new operator No new() operator ! ! return pizza.! pizza.factory = factory.! ! ! pizza = factory.prepare().! ! public PizzaStore(SimplePizzaFactory factory) {! ! ! this.bake().! ! }! ! public Pizza orderPizza(String type) {! ! ! Pizza pizza.

   Example:  Revised  Class  Diagram     14 .

Simple  Factory   •  Pull  the  code  that  builds  the  instances  out  and   put  it  into  a  separate  class     – Iden-fy  the  aspects  of  your  applica-on  that  vary   and  separate  them  from  what  stays  the  same   15 .

Simple  Factory  Pa]ern   Client orderProduct() SimpleFactory createProduct() <<abstract>> Product productMethod() ConcreteProductA ConcreteProductB ConcreteProductC 16 .

Why  would  we  do  this?   •  Mul-ple  clients    needing  same  types  of  object   •  Ensure  consistent  object  ini-aliza-on   17 .

 customers  in     Chicago  prefer  a  thick  base.    However.  customers  at  the  franchise   in  New  York  like  a  thin  base.   18 .g.  with  tasty  sauce     and  li]le  cheese.    For  example.    Some  franchises  also  cut  the     pizza  slices  differently  (e.    Example:  System  Revision  Again   Franchises  in  different  parts  of  the  country  are     now  adding  their  own  special  touches  to  the     pizza.  rich  sauce  and  a     lot  of  cheese.  square)   You  need  to  extend  the  system  to  cater  for  this.

 but  lets  the  subclasses  decide   which  class  to  instan-ate.   •         Factory  Method  lets  a  class  defer  instan-a-on  to   subclasses.   19 .The  Factory  Method   Defini-on:     •         The  factory  Method  Pa]ern  defines  an  interface  for   crea-ng  an  object.

Creator  Class   20 .

Product  Class   21 .

public abstract class PizzaStore {! ! ! ! public Pizza orderPizza(String type) {! ! ! Pizza pizza.! ! }! abstract Pizza createPizza(String type).cute().! ! ! ! ! ! ! ! ! pizza.! pizza.! pizza.! pizza.prepare().! ! ! pizza = createPizza(type).! No new operator ! ! return pizza.box().bake().! }! 22 .

! ! !! } else return null.equals(“pepperoni”)) {! ! !! ! return new NYStylePepperoniPizza().! ! !! } else if (type.! }! }! 23 .! ! !! } else if (type.equals(“cheese”)) {! ! !! ! return new NYStyleCheesePizza().public class NYPizzaStore extends PizzaStore{! Pizza createPizza(String item) {! ! !! if (type.equals(“veggie”)) {! ! !! ! return new NYStyleVeggiePizza().

Structure   24 .

Factory  Method  Pa]ern   <<abstract>> Product IS-A ConcreteProduct HAS-A <<abstract>> Creator factoryMethod() operation() IS-A ConcreteCreator factoryMethod() abstract! No more SimpleFactory class Object creation is back in our class. but … delegated to concrete classes 25 .

Applicability   •  Use  Factory  Method  when:   – A  class  can’t  an-cipate  the  class  of  objects  it  must   create   – A  class  wants  its  subclasses  to  specify  the  objects   it  creates   – Classes  delegate  to  one  of  several  helper   subclasses.  and  you  want  to  localize  knowledge   about  which  is  the  delegate   26 .

Par-cipants   •  Product   – Defines  interface  of  objects  to  be  created   •  ConcreteProduct   – Implements  Product  interface   •  Creator   – Declares  factory  method   •  Returns  object  of  type  Product   •  May  define  default  implementa-on   – May  call  factory  method  to  create  Products   27 .

Consequences   •  Eliminates  need  to  bind  crea-on  code  to   specific  subclasses   •  May  need  to  subclass  Creator  for  each   ConcreteProduct   •  Provides  hooks  for  subclasses   •  Connects  parallel  class  hierarchies   28 .

 but   Doesn’t  know  what  type  of  Document  to  create   – Factory  Method  moves  knowledge  about  specific   Document  subclass  out  of  framework   29 .An  Example   •  Applica-on  framework   – App  subclasses  “Applica-on.”  “Document”   – Framework  knows  when  to  create  Document.

  30 .Guidelines   •  No  variable  should  hold  a  reference  to  a   concrete  class   •  No  class  should  derive  from  a  concrete  class   •  No  method  should  override  an  implemented   method  of  an  of  its  base  classes.

  orderPizza.   •  The  creator  specifies  the  “factory  method”.   •  Only  subclasses  implement  the  factory   method.   e.Summary   •  The  creator  gives  you  an  interface  for  wri-ng   objects.  the  createPizza  method.g.g.   31 .   •  Other  methods  generally  included  in  the   creator  are  methods  that  operate  on  the   product  produced  by  the  creator.  e.

Summary   •   Simple  Factory   –  Use  when  you  have  only  one  family  of  objects   •  Factory  Method  Pa]ern   –  Use  when  you  have  mul-ple  families  of  objects   •  Abstract  Factory  (next  -me)   –  Use  when  you  have  mul-ple  families  of  object  components   32 .

  •  Programming  to  interface  not   implementa-on.   •  Client  code  is  decoupled  from  actual   implementa-ons.Thoughts…   •  When  you  have  code  that  instan-ates   concrete  classes  that  may  change.   •  The  factory  pa]ern  allows  you  to  encapsulate   the  behaviour  of  the  instan-a-on.  encapsulate   the  code  that  changes.   33 .   •  Duplica-on  of  code  is  prevented.