KEMBAR78
04 - Factory Method Pattern | PDF | Method (Computer Programming) | Class (Computer Programming)
0% found this document useful (0 votes)
20 views28 pages

04 - Factory Method Pattern

The document discusses the Factory Method design pattern, emphasizing the importance of encapsulating object creation to enhance code flexibility and maintainability. It illustrates the transition from using concrete classes directly to employing a factory that creates objects based on specified types, allowing for easier modifications and extensions. The document also highlights the differences between the Simple Factory and Factory Method patterns, noting that the latter allows subclasses to define the creation logic while maintaining a consistent interface for object usage.

Uploaded by

Batuhan Ekinci
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views28 pages

04 - Factory Method Pattern

The document discusses the Factory Method design pattern, emphasizing the importance of encapsulating object creation to enhance code flexibility and maintainability. It illustrates the transition from using concrete classes directly to employing a factory that creates objects based on specified types, allowing for easier modifications and extensions. The document also highlights the differences between the Simple Factory and Factory Method patterns, noting that the latter allows subclasses to define the creation logic while maintaining a consistent interface for object usage.

Uploaded by

Batuhan Ekinci
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 28

BIM492 DESIGN PATTERNS

04. FACTORY PATTERNS

Baking with OO Goodness


When you see "new", think "concrete"
When you use "new", you instantiate a concrete class
--> that’s programming to implementation, not interface
Duck duck = new MallardDuck();

When you have a whole set of related concrete classes:


Duck duck; If you need changes or extensions to this code
if (picnic) {
duck = new MallardDuck(); you’ll have to reopen it and examine what
} else if (hunting) { needs to be added (or deleted).
duck = new DecoyDuck();
} else if (inBathTub) {
duck = new RubberDuck(); This kind of code makes maintenance and updates
} more difficult and error-prone.

2
What’s wrong with "new"?
• Technically there’s nothing wrong with new
• After all, it’s a fundamental part of Java
• Our problem is with CHANGE
• And how change impacts our use of new
DO YOU REMEMBER OUR FIRST DESIGN PRINCIPLE?
identify the aspects that vary and separate them from what
stays the same
 You know you can insulate yourself from changes by coding to an interface
 HOW? --> through polymorphism
 If you program to implementation, your code will not be "closed for modification"
 to extend with new behavior, you’ll have to reopen it
 So what can you do?

3
Identifying the aspects that vary we'll run a pizza shop today
Pizza orderPizza() {
Pizza pizza = new Pizza();

pizza.prepare(); Pizza orderPizza(String type) {


pizza.bake(); Pizza pizza;
pizza.cut();
pizza.box(); if (type.equals("cheese")) {
return pizza; pizza = new CheesePizza();
} } else if (type.equals("greek") {
But we need more than one type of pizza… pizza = new GreekPizza();
} else if (type.equals("pepperoni") {
• we need to determine the appropriate type pizza = new PepperoniPizza();
• then we go on making the pizza }

pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
4
But the pressure is on to add more pizza types
Pizza orderPizza(String type) {
Pizza pizza;

if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("greek") {
pizza = new GreekPizza();
} else if (type.equals("pepperoni") {
pizza = new PepperoniPizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza();
} else if (type.equals("veggie") {
pizza = new VeggiePizza();
} Clearly, dealing with which
pizza.prepare(); concrete class is instantiated is
pizza.bake(); really messing up our
pizza.cut(); orderPizza() method.
pizza.box();
return pizza; It's time to encapsulate it.
}
5
Take the creation code and
Encapsulating object creation
move it out into another
object concerned only with
creating pizzas.

We've got a name for this new object:


FACTORY
SimplePizzaFactory handles creation of
pizza objects.
Gone are the days when orderPizza()
need to know about Greek vs. Clam
pizzas.

Let's implement a simple factory…

6
Building a simple pizza factory

there are no
Dumb Questions
public class SimplePizzaFactory { Q: What is the advantage of this? It looks
public Pizza createPizza(String type) {
like we’re just pushing the problem off to
Pizza pizza = null;
another object?
if (type.equals("cheese")) {
pizza = new CheesePizza(); A: One thing to remember is that the
} else if (type.equals("pepperoni")) { SimplePizzaFactory may have many clients.
pizza = new PepperoniPizza();
We’ve only seen the orderPizza()
} else if (type.equals("clam")) {
pizza = new ClamPizza(); method; however, there may be a
} else if (type.equals("veggie")) { PizzaShopMenu class that uses the factory.
pizza = new VeggiePizza();
} So, by encapsulating the pizza creating in
return pizza; one class, we now have only one place to
} make modifications when the implementation
} changes.
7
Reworking the PizzaStore class
public class PizzaStore {
SimplePizzaFactory factory;

public PizzaStore(SimplePizzaFactory factory) {


this.factory = factory;
}

public Pizza orderPizza(String type) {


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

8
The Simple Factory defined
The Simple Factory isn’t
actually a Design Pattern,
it’s more of a programming
idiom.

″Implement an interface″
does NOT always mean
″write a class that
implements a Java
interface, by using the
″implements″ keyword in
the class declaration″.
In the general sense of the
phrase, a concrete class
implementing a method
from a supertype (a class
OR interface) is still to be
considered ″implementing
the interface″.
9
Franchising the pizza store
• Everyone wants our pizza in their neighborhood, so we start franchising.
• But what about regional differences (New York, Chicago, and California styles)

We’ve seen one approach…


Create three different
factories, NYPizzaFactory,
ChicagoPizzaFactory, and
CaliforniaPizzaFactory.
Let’s see how it works..

10
NYPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.order(“Veggie”);

ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();


PizzaStore chicagoStore = new PizzaStore(chicagoFactory);
chicagoStore.order(“Veggie”);

But you’d like a little more quality control


Rethinking the problem a bit, you see that what you’d really like to do is create a
framework that ties the store and the pizza creation together, yet still allows things to
remain flexible.
11
A framework for the pizza store
There is a way to localize all the pizza making
activities to the PizzaStore class, and yet give
public abstract class PizzaStore { the franchises freedom to have their own
regional style.
public Pizza orderPizza(String type) {
Pizza pizza; What we’re going to do is put the
createPizza() method back into
pizza = createPizza(type); PizzaStore, but this time as an abstract
method, and then create a PizzaStore subclass
pizza.prepare();
pizza.bake(); for each regional style.
pizza.cut();
pizza.box();

return pizza;
}

abstract createPizza(String type);


}

12
Allowing the subclasses
decide
 Each subclass of PizzaStore
define what the
createPizza() method
looks like.
 A number of concrete
subclasses of PizzaStore,
each with its own
variations.
 Yet, all use our well-tuned
orderPizza() method. It is
consistent across all
franchises.

13
Well, think about it from the point of view of PizzaStore’s orderPizza()

Now, take this a litle further,


orderPizza() method does a lot of When orderPizza() calls createPizza(), one
things with a Pizza object, but because of your subclasses will be called into action to create a
Pizza is abstract, orderPizza() has pizza. Which kind of pizza will be made? That’s decided
no idea what real concrete classes are by the choice of pizza store you order from,
involved. It’s decoupled! NYStylePizzaStore or ChicagoStylePizzaStore.

So, there is no real-time deciding here. Subclasses


aren’t really deciding, YOU’re deciding. But
orderPizza() doesn’t care who decides, it just don’t.

14
Let’s make a PizzaStore

public class NYPizzaStore extends PizzaStore {


Pizza createPizza(String item) {
if (item.equals("cheese")) {
return new NYStyleCheesePizza();
} else if (item.equals("veggie")) {
return new NYStyleVeggiePizza();
} else if (item.equals("clam")) {
return new NYStyleClamPizza();
} else if (item.equals("pepperoni")) {
return new NYStylePepperoniPizza();
} else return null;
}
}
15
Declaring a factory method
public abstract class PizzaStore {

public Pizza orderPizza(String type) {


Pizza pizza; pizza = createPizza(type);

pizza.prepare();

pizza.bake();
pizza.cut();
pizza.box(); With just a couple
return pizza;
transformations to the
}
PizzaStore we’ve gone from
protected abstract Pizza createPizza(String type); having an object handle the
instantiation of our concrete
// other methods here classes to a set of subclasses
} that are now taking on that
responsibility.
16
Declaring a factory method, continued…

17
Let’s see how it works: ordering pizzas with the pizza factory method

So how do they order?


1. First, they need a PizzaStore. Joel needs
ChicagoPizzaStore and Ethan needs
NYPizzaStore.
2. Both call orderPizza() method and pass
in the type of pizza (Cheese, veggie, etc.)
3. Then, createPizza() method is called
which is defined in NYPizzaStore and
ChicagoPizzaStore. Pizza is returned to
orderPizza() method.
4. So, orderPizza() has no idea what kind
of pizza was created, but it is a Pizza for
sure, so it bakes, cuts, boxes them for Ethan
and Joel.
18
Let’s check out how these
pizzas are really made to order…
1. Let’s follow Ethan’s order: first we need a NYPizzaStore:
PizzaStore nyPizzaStore = new NYPizzaStore();

2. Now that we have a store, we can take an order:


nyPizzaStore.orderPizza(″cheese″);

3. The orderPizza() method then calls the createPizza():


Pizza pizza = createPizza(″cheese″);

4. Finally we have the unprepared pizza in hand and the


orderPizza() method finishes preparing it.
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();

19
We’re just missing
one thing: PIZZA !
public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();

void prepare() {
System.out.println(“Preparing “ + name);
System.out.println(“Tossing dough...”);
System.out.println(“Adding sauce...”);
System.out.println(“Adding toppings: “);
for (int i = 0; i < toppings.size(); i++) {
System.out.println(“ “ + toppings.get(i));
}
}

void bake() {
System.out.println(“Bake for 25 minutes at 350”);
}

void cut() {
System.out.println(“Cutting the pizza into diagonal slices”);
}

void box() {
System.out.println(“Place pizza in official PizzaStore box”);
}

public String getName() { return name; } }


20
Now, we just need some concrete subclasses… Cheese pizza?

public class NYStyleCheesePizza extends Pizza {


public NYStyleCheesePizza() {
name = “NY Style Sauce and Cheese Pizza”;
dough = “Thin Crust Dough”;
sauce = “Marinara Sauce”;
toppings.add(“Grated Reggiano Cheese”);
}
}

public class ChicagoStyleCheesePizza extends Pizza {


public ChicagoStyleCheesePizza() {
name = “Chicago Style Deep Dish Cheese Pizza”;
dough = “Extra Thick Crust Dough”;
sauce = “Plum Tomato Sauce”;
toppings.add(“Shredded Mozzarella Cheese”);
}
void cut() {
System.out.println(“Cutting the pizza into square slices”);
}
}
21
It’s time for Pizzas, let’s make a teste
public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();
Pizza pizza = nyStore.orderPizza(“cheese”);
System.out.println(“Ethan ordered a “ + pizza.getName() + “\n”);
pizza = chicagoStore.orderPizza(“cheese”);
System.out.println(“Joel ordered a “ + pizza.getName() + “\n”);
}
}

22
Meet the Factory Method Pattern
The Creator classes
! All factory patterns
encapsulate object creation

The Product classes

23
Another perspective: palallel class hierarchies
 Encapsulating knowledge into
each creator.

24
Factory Method Pattern defined

25
Consequences of Factory Method Pattern
 Benefits
 It makes your code more flexible and reusable by decoupling the creation of application-specific instances.
 The code only deals with the Product interface so it can work with any user-defined ConcreteProduct classes.
 Liabilities
 Clients might have to subclass the Creator class just to instantiate a particular ConcreteProduct

26
there are no
Dumb Questions
Q: What's the advantage of the Factory Method Pattern Q: Are the factory method and the Creator always abstract?
when you only have one ConcreteCreator? A: No, you can define a default factory method to produce
A: The Factory Method Pattern is useful if you've only got some concrete product. Then you always have a means of
one concrete creator because you are decoupling the creating products even if there are no subclasses of the
implementation of the product from its use. If you add Creator.
additional products or change a product's implementation, it
will not affect your Creator (because the Creator is not Q: Each store can make four different kinds of pizzas based
tightly coupled to any ConcreteProduct). on the type passed in. Do all concrete creators make multiple
Q: Would it be correct to say that our NY and Chicago products, or do they sometimes just make one?
stores are implemented using Simple Factory? A: We implemented what is known as the parameterized
factory method. It can make more than one object based on a
A: They're similar, but used in different ways. Even though parameter passed in, as you noticed. Often, however, a factory
the implementation of each concrete store looks a lot like just produces one object and is not parameterized. Both are
the SimplePizzaFactory, remember that the concrete stores valid forms of the pattern.
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. In Simple
Factory, the factory is another object that is composed with
the PizzaStore.
27
there are no
Dumb Questions
Q: Your parameterized types don't seem "type-safe." I'm Q: I'm still a bit confused about the difference between Simple
just passing in a String! What if I asked for a "CalmPizza"? Factory and Factory Method. They look very similar, except
that in Factory Method, the class that returns the pizza is a
A: You are certainly correct and that would cause, what we
subclass. Can you explain?
call in the business, a "runtime error". There are several
other more sophisticated techniques that can be used to A: You're right that the subclasses do look a lot like Simple
make parameters more "type safe", or, in other words, to Factory, however think of Simple Factory as a one shot deal,
ensure errors in parameters can be caught at compile time. while with Factory Method you are creating a framework that
For instance, you can create objects that represent the lets the subclasses decide which implementation will be used.
parameter types, use static constants, or, in Java 5, you can For example, the orderPizza() method in the Factory
use enums. Method provides a general framework for creating pizzas that
relies on a factory method to actually create the concrete
classes that go into making a pizza. By subclassing the
PizzaStore class, you decide what concrete products go into
making the pizza that orderPizza() returns. Compare that
with SimpleFactory, which gives you a way to encapsulate
object creation, but doesn't give you the flexibility of the
Factory Method because there is no way to vary the products
you're creating.
28

You might also like