Professional Documents
Culture Documents
Factory and Abstract Factory Pattern
Factory and Abstract Factory Pattern
When you have a whole set of related concrete classes, often you’re
forced to write code like this:
Duck duck;
if (picnic) {
fferent
duck = new MallardDuck();
} else if (hunting) { We have a bunch of didon’t know
duck = new DecoyDuck(); duck classes, and we e we need
} else if (inBathTub) {
until runtime which on
to instantiate.
duck = new RubberDuck();
}
Here we’ve got several concrete classes being instantiated, and the
decision of which to instantiate is made at runtime depending on
some set of conditions.
When you see code like this, you know that when it comes time for
changes or extensions, you’ll have to reopen this code and examine
what needs to be added (or deleted). Often this kind of code ends
up in several parts of the application making maintenance and
updates more difficult and error-prone.
the factory pattern
brain
A power
How might you take all the parts of your application that instantiate concrete classes and
separate or encapsulate them from the rest of your application?
identify what varies
Pizza orderPizza() {
Pizza pizza = new Pizza();
So then you’d add some code that determines the appropriate type of pizza
and then goes about making the pizza:
Clearly, dealing with which concrete class is instantiated is really messing up our
orderPizza() method and preventing it from being closed for modification. But now
that we know what is varying and what isn’t, it’s probably time to encapsulate it.
encapsulate object creation
into another object that is only going to be concerned with } else if (type.equals(“pepperoni”) {
pizza = new PepperoniPizza();
creating pizzas.
} else if (type.equals(“clam”) {
pizza = new ClamPizza();
} else if (type.equals(“veggie”) {
pizza = new VeggiePizza();
}
plePizzaFactory. It has a n
Here’s our new class, the Sim s for its clients. e d efine method i e
one job in life: creating pizza w ) t h
First tePizza( . This is ill use to
crea factory lients w cts.
the hod all c new obje
met ntiate
public class SimplePizzaFactory { insta
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals(“cheese”)) {
pizza = new CheesePizza();
} else if (type.equals(“pepperoni”)) { Here’s the code we
pizza = new PepperoniPizza(); plucked out of the
} else if (type.equals(“clam”)) {
pizza = new ClamPizza();
orderPizza() method.
} else if (type.equals(“veggie”)) {
pizza = new VeggiePizza();
}
return pizza;
}
}
pizza = factory.createPizza(type);
The Simple Factory isn’t actually a Design Pattern; it’s more of a programming
idiom. But it is commonly used.
Just because Simple Factory isn’t a REAL pattern doesn’t mean we shouldn’t check out
how it’s put together. Let’s take a look at the class diagram of our new Pizza Store:
a
We’ve defined Pizzs
PizzaStore SimplePizzaFactory Pizza as an abstract cl as
orderPizza() createPizza() prepare() with some helpful at
bake() implementations th
cut()
can be overridden.
d is often
box()
nt of the The create metho .
This is the clieaStore
factory. Pizz ugh the declared statically
now goes throactory to get
SimplePizzaF zza. CheesePizza PepperoniPizza
instances of pi
VeggiePizza ClamPizza
These are our concrete products.
product needs to implement the Each
Pizza
interface* (which in this case mea
“extend the abstract Pizza class”) ns
be concrete. As long as that’s the and
it can be created by the factor case,
handed back to the client. y and
Think of Simple Factory as a warm up. Next, we’ll explore two heavy duty patterns
that are both factories. But don’t worry, there’s more pizza to come!
*Just another reminder: in design patterns, the phrase “implement an interface” does NOT always mean
“write a class the implements a Java interface, by using the “implements” keyword in the class declaration.” In
the general use of the phrase, a concrete class implementing a method from a supertype (which could be a
class OR interface) is still considered to be “implementing the interface” of that supertype.
pizza franchise
ry
izzaFacto
Piz
zaStore Another franchise
wants a factory that
makes Chicago style
ory
hi
pizzas; their customers
cag like pizzas with thick
C
ct
a
oPizzaF crust, rich sauce, and
tons of cheese.
good
Not what you want in a want to know
franchise. You do NOT s.
what he puts on his pizza
let the subclasses decide
Now we’ve got a store waiting for subclasses; we’re going to have a
subclass for each regional type (NYPizzaStore, ChicagoPizzaStore,
CaliforniaPizzaStore) and each subclass is going to make the decision about
what makes up a pizza. Let’s take a look at how this is going to work.
the factory pattern
NYStylePizzaStore ChicagoStylePizzaStore
Similarly, by using the
If a franchise wants NY style createPizza() createPizza()
Chicago subclass, we get an
pizzas for its customers, it implementation of createPizza()
uses the NY subclass, which has with Chicago ingredients.
its own createPizza() method, Remember: createPizza() is
creating NY style pizzas. abstract in PizzaStore, so all
pizza store subtypes MUST
implement the method.
Well, think about it from the point of view of the PizzaStore’s orderPizza() method: it is
defined in the abstract PizzaStore, but concrete types are only created in the subclasses.
in the abstract
orderPizza() is defined classes. So, the
PizzaStore
NYStylePizzaStore ChicagoStylePizzaStore
createPizza() createPizza()
So, is there a real-time decision that subclasses make? No, but from the perspective of
orderPizza(), if you chose a NYStylePizzaStore, that subclass gets to determine which
pizza is made. So the subclasses aren’t really “deciding” – it was you who decided by
choosing which store you wanted – but they do determine which kind of pizza gets made.
the factory pattern
instantiation fo ethod.
createPizza() m
public Pizza orderPizza(String type) {
Pizza pizza; NYStylePizzaStore
createPizza()
pizza = createPizza(type);
pizza.prepare();
ChicagoStylePizzaStore
pizza.bake();
createPizza()
pizza.cut();
pizza.box();
return pizza;
}
All the responsibility for
instantiating Pizzas has been
protected abstract Pizza createPizza(String type);
Code Up Close
A factory method handles object creation and encapsulates it in
hod may be
A factory met (or not)
a subclass. This decouples the client code in the superclass from
parameterized several
the object creation code in the subclass.
A factory method
abstract so the su is lates the client (the
bc la ss
A factory method returns A factory method iso like orderPizza())
are counted on to
ha nd
es a Product that is typically code in the superclass, d of concrete
object creation. le used within methods defined from knowing what kineated.
in the superclass. Product is actually cr
the factory pattern
Creates a instance of
NYPizzaStore.
e
nyPizzaStore.orderPizza(“cheese”);
createPizza(“cheese”)
is called on
The orderPizza() methode (the method
the nyPizzaStore instance runs).
defined inside PizzaStor
pizza.prepare();
pizza.bake(); e defined
pizza.cut(); All of these methods arturned
pizza.box(); in the specific pizza re od
from the factory meth in the
createPizza(), defined
od gets NYPizzaStore.
The orderPizza() methknowing
t
back a Pizza, withou class it is.
exactly what concrete
the pizza classes
ract
with an abst
We’ll start and all the concrete
Pizza class derive from this.
pizzas will
gh, a
public abstract class Pizza { Each Pizza has a name, a type of dous.
String name; type of sauce, and a set of topping
String dough;
String sauce;
ArrayList toppings = new ArrayList();
void cut() {
System.out.println(“Cutting the pizza into diagonal slices”);
}
void box() {
System.out.println(“Place pizza in official PizzaStore box”);
}
pizza = chicagoStore.orderPizza(“cheese”);
System.out.println(“Joel ordered a “ + pizza.getName() + “\n”);
}
}
%java PizzaTestDrive
NYStyleClamPizza ChicagoStyleClamPizza
NYStyleVeggiePizza ChicagoStyleVeggiePizza
creators and products
createPizza()
orderPizza()
NYStyleClamPizza ChicagoStyleClamPizza
tes
NYStyleVeggiePizza ChicagoStyleVeggiePizza
psula to e
o r e n c
e howa
z z a Stor
St ut P i
Y P izza edge aboas. C h icago s all the ow to .
N l z e e
Th apsulat about h pizzas
The the know tyle piz
all e NY s enc ledge go style
mak know e Chica
mak
ledge.
y to encapsul ating this know
ethod is the ke
The factory m
factory method defined
As with every factory, the Factory Method Pattern gives us a way to encapsulate the
instantiations of concrete types. Looking at the class diagram below, you can see that the
abstract Creator gives you an interface with a method for creating objects, also known as the
“factory method.” Any other methods implemented in the abstract Creator are written to
hat
them wwe bet
operate on products produced by the factory method. Only subclasses actually implement
the factory method and create products. ul d a s k t
You co s” means, bu d this
i d e a n
“dec ow underst do !
As in the official definition, you’ll often hear developers say that the Factory Method lets
subclasses decide which class to instantiate. They say “decides” not because the pattern
you n r than they
allows subclasses themselves to decide at runtime, but because the creator class is written bette
without knowledge of the actual products that will be created, which is decided purely by
the choice of the subclass that is used.
ains
a class that cont
The Creator is tions for all of the
the implementa ipulate products,
methods to man factory method.
except for the
Product Creator
factoryMethod(), which is
factoryMethod()
Q: What’s the advantage of the Factory Method A: We implemented what is known as the
Pattern when you only have one ConcreteCreator? parameterized factory method. It can make more than
one object based on a parameter passed in, as you
Q: Would it be correct to say that our NY and A: You are certainly correct and that would cause,
what we call in the business, a “runtime error.” There
Chicago stores are implemented using Simple
Factory? They look just like it. are several other more sophisticated techniques that
can be used to make parameters more “type safe”, or,
A:
in other words, to ensure errors in parameters can be
They’re similar, but used in different ways. Even caught at compile time. For instance, you can create
though the implementation of each concrete store looks objects that represent the parameter types, use static
a lot like the SimplePizzaFactory, remember that the constants, or, in Java 5, you can use enums.
concrete stores are extending a class which has defined
createPizza() as an abstract method. It is up to each
store to define the behavior of the createPizza() method.
Q: I’m still a bit confused about the difference
between Simple Factory and Factory Method. They
In Simple Factory, the factory is another object that is
look very similar, except that in Factory Method, the
composed with the PizzaStore.
class that returns the pizza is a subclass. Can you
Q:
explain?
Are the factory method and the Creator
always abstract?
A: You’re right that the subclasses do look a lot
like Simple Factory, however think of Simple Factory
A: No, you can define a default factory method
to produce some concrete product. Then you always
as a one shot deal, while with Factory Method you are
creating a framework that let’s the subclasses decide
have a means of creating products even if there are no which implementation will be used. For example, the
subclasses of the Creator. orderPizza() method in the Factory Method provides a
general framework for creating pizzas that relies on a
Let’s pretend you’ve never heard of an OO factory. Here’s a version of the PizzaStore that
doesn’t use a factory; make a count of the number of concrete pizza objects this class is
dependent on. If you added California style pizzas to this PizzaStore, how many objects would it
be dependent on then?
izzaSto
re
P
giePizza
Ch
Pizza
ica
oS
NY
eg
ty tyleV
g
le oni P z a
S
Che e
se
i z
Ch
i ca
go
Pizza
ty
er
lePepp
S
NY
ty
Pizza
le
S
Ve g g
Ch
ie
iPizza
ica
NY
oS
lam
tyleC
g
St
eP
ePizza
yl
e p pe r
on
Ch
NY
zz a
ty
es
ica
le
S
Clam oS
Pi
he
tyleC
g
nds only
PizzaStore now depect class.
Piz
zaStor on Pizza, the ab st ra
e
Pizza is an abstract
class...an abstraction. classes depend on
The concrete pizza too, because they
the Pizza abstractioninterface (remember,
implement the Pizza e” in the general
we’re using “interfac stract class.
Pizza
NY
zz a
ty ty
le le
S
Che e
se
Clam
Pi
iPizza
Pizza
NY
NY
ty
St
giePizza
eP le
S
Ve g g
i za
ie
yl
e p pe r
on
Ch
Ch
oniP z
i ca
ica
oS
eg
go
tyleV
g
ty
ePizza
er
lePepp
S
Pizza
Ch
Ch
es
ica
ica
oS oS
lam
he
tyleC tyleC
g
After applying the Factory Method, you’ll notice that our high-level component,
the PizzaStore, and our low-level components, the pizzas, both depend on Pizza,
the abstraction. Factory Method is not the only technique for adhering to the
Dependency Inversion Principle, but it is one of the more powerful ones.
the factory pattern
Clam Pizza
Clam Pizza
san, Clams Marinara Sauce, Reggiano, Fresh Clams
Plum Tomato Sauce, Mozzarella, Parme
Pepperoni Pizza
Pepperoni Pizza
san, Marinara Sauce, Reggiano, Mushrooms,
Plum Tomato Sauce, Mozzarella, Parme
oni Onions, Red Peppers, Pepperoni
Eggplant, Spinach, Black Olives, Pepper
the factory pattern
Families of ingredients...
New York uses one set of Chicago
ingredients and Chicago another.
Given the popularity of Objectville FrozenClams
MarinaraSauce ThinCrustDough
California
ReggianoCheese
Calamari
BruschettaSauce VeryThinCrust
GoatCheese
Each family consists of a type of dough,
a type of sauce, a type of cheese, and a
seafood topping (along with a few more we
haven’t shown, like veggies and spices).
lies, with
e th re e re gio ns ma ke up ingredient fami ents.
In total, th es of ingre di
ing a complete family
each region implement
ingredient factories
ea
public Dough createDough();
ea ch in gr ed ient we defin ce.
public Sauce createSauce(); For in our interf a
public Cheese createCheese(); create method
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
nery”
If we’d had some common “machi
Lots of new classes here, to implement in each inst anc e of
one per ingredient. factory, we could have made thi
s an
abstract class instead ...
ient in the
return new ThinCrustDough();
} For each ingredily, we create
ingredient fam version.
the New York
public Sauce createSauce() {
return new MarinaraSauce();
}
void cut() {
System.out.println(“Cutting the pizza into diagonal slices”);
}
void box() {
System.out.println(“Place pizza in official PizzaStore box”);
}
we need
public class CheesePizza extends Pizza { To make a pizza now,e the
PizzaIngredientFactory ingredientFactory; a factory to provid Pizza
ingredients. So each
{ ss gets a factory passed
public CheesePizza(PizzaIngredientFactory ingredientFactory)
cla and it’s
into its constructor,e variable.
this.ingredientFactory = ingredientFactory;
stored in an instanc
}
void prepare() {
System.out.println(“Preparing “ + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce(); Here’s where the magic happens!
cheese = ingredientFactory.createCheese();
}
}
Code Up Close
The Pizza code uses the factory it has been composed with to produce the ingredients used in the
pizza. The ingredients produced depend on which factory we’re using. The Pizza class doesn’t care;
it knows how to make pizzas. Now, it’s decoupled from the differences in regional ingredients and
can be easily reused when there are factories for the Rockies, the Pacific Northwest, and beyond.
sauce = ingredientFactory.createSauce();
a NY
t o r e is c o m posed with will
public class NYPizzaStore extends PizzaStore { The NY S dient factory. This s
pizza ingre produce the ingredient
protected Pizza createPizza(String item) { be used to style pizzas.
Pizza pizza = null; for all NY
PizzaIngredientFactory ingredientFactory =
new NYPizzaIngredientFactory();
} else if (item.equals(“clam”)) {
Defines the
introducing a new type of
factory called an Abstract interface.
Factory.
Ethan and Joel can’t get enough Object ville Pizza! What they
don’t know is that now their orders are making use of the
new ingredient factories. So now when they order...
Creates an instance of
NYPizzaStore.
n yP r
izzaSto
e
2 Now that we have a store, we can take an order:
nyPizzaStore.orderPizza(“cheese”);
is called on
the orderPizza() method e.
the nyPizzaStore instanc
ese”)
zza(“che
createPi
3 The orderPizza() method first calls the cre-
atePizza() method:
Creates a instance of
Pizza that is composed
t or y
yI
with the New York ngr
ac
edientF
ingredient factory.
Pizza
prepare()
prepare() method is called, the factory is asked
to prepare ingredients:
ust
void prepare() { Thin cr
dough = factory.createDough();
Marinara
sauce = factory.createSauce();
cheese = factory.createCheese();
} Reggiano
w York
For Ethan’s pizza the Ned, and so we
ingredient factory is use
get the NY ingredients.
We’ve certainly seen that Abstract Factory allows a client to use an abstract interface to
create a set of related products without knowing (or caring) about the concrete products that
are actually produced. In this way, the client is decoupled from any of the specifics of the
concrete products. Let’s look at the class diagram to see how this all holds together:
The Client is written against the
abstract factory and then composed at
runtime with an actual factory.
ProductA2 ProductA1
ConcreteFactory1 ConcreteFactory2
CreateProductA() CreateProductA()
CreateProductB() CreateProductB()
<<interface>>
AbstractProductB
Pizza
prepare()
// other methods
ThickCrustDough ThinCrustDough
<<interface>>
PizzaIngredientFactory
createDough()
createSauce() <<interface>>
createCheese() Sauce
createVeggies()
createPepperoni()
createClam() PlumTomatoSauce MarinaraSauce
NYPizzaIngredientFactory ChicagoPizzaIngredientFactory
<<interface>>
createDough() createDough() Cheese
createSauce() createSauce()
createCheese() createCheese()
createVeggies() createVeggies() Mozzarella Cheese ReggianoCheese
createPepperoni() createPepperoni()
createClam() createClam()
<<interface>>
Clams
Pizza
NYStyleCheesePizza ChicagoStyleCheesePizza
NYStylePepperoniPizza Subclasses are instaniated ChicagoStylePepperoniPizza
NYStyleClamPizza by the Factory Methods. ChicagoStyleClamPizza
NYStyleVeggiePizza ChicagoStyleVeggiePizza
an
ry is implemented as
PizzaIngredientFactocause we need to create
Abstract Factory be(the ingredients). Each
<<interface>> families of products e ingredients using its own
subclass implements th
PizzaIngredientFactory
regional suppliers.
createDough()
family of products.
createVeggies()
New York
NYPizzaIngredientFactory ChicagoPizzaIngredientFactory Chicago
createDough() createDough()
createSauce() createSauce()
<<interface>> <<interface>>
Dough Clams
Each ingredient
represents a
product that is
<<interface>> <<interface>>
produced by a d
Sauce Cheese
Factory Metho
in the Abstract
Factory.
MarinaraSauce PlumTomatoSauce ReggianoCheese Mozzarella Cheese
OO Basics
fide design pattern, is a simple
way to decouple your clients
from concrete classes.
s
OO Principle
Abstraction ß Factory Method relies on
n
.
Encapsulatio inheritance: object creation is
what varies
olymorphism
delegated to subclasses which
Encapsulate
n ov er in heritanceP. implement the factory method to
Inheritance
sit io
Favor compo create objects.
, not
Program tat o interfaces
ions. ß Abstract Factory relies on object
implement designs composition: object creation
ve f or lo os ely coupledteract.
Stri cts that in We have a new principle that is implemented in methods
between obje tension exposed in the factory interface.
b e open for ex guides us to keep things
sh ou ld
Classes for modification. abstract whenever possible. ß All factory patterns promote
but closed
Do not
stractions. ses.
loose coupling by reducing the
en d on ab
Dep ncrete clas dependency of your application
depend on co on concrete classes.
ß The intent of Factory Method
w patterns
Both of these nect creation is to allow a class to defer
encapsulate obje e decoupled, instantiation to its subclasses.