0% found this document useful (0 votes)
7 views19 pages

Day05_AbstractFactory

Uploaded by

cuongcog04
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)
7 views19 pages

Day05_AbstractFactory

Uploaded by

cuongcog04
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/ 19

Design Patterns

Week 5: Abstract Factory


Vũ Đình Hồng

9/7/2016 1
Pizza
public class Pizza {

Dough dough;
Sauce sauce;
Pizza becomes composed of
Veggies veggies[];
different ingredients.
Cheese cheese;
Pepperoni pepperoni;
Clams clam;

Question: How do we
. . . get these ingredients
associated with a
} Pizza??

9/7/2016 2
One idea…Constructor w/many
parameters
public class Pizza {

public Pizza(Dough d, Sauce s, Cheese c, Veggies v,


Pepperoni p, Clams c) {

this.dough = d;
this.sauce = s;
this.veggies = v;
this.cheese = c; Makes sense…whenever
this.pepperoni = p; you create a pizza, you
must specify these
this.clam = c;
ingredients…
}
}

9/7/2016 3
Rework NYPizzaStore
public class NYPizzaStore extends PizzaStore {

Pizza createPizza(String item) {

if (item.equals("cheese")) {
return new NYStyleCheesePizza(new ThinCrustDough(),
new Marinara(), new Reggiano(), null, null );

} else if (item.equals("veggie")) {
return new NYStyleVeggiaPizza(new ThinCrustDough(),
new Marinara(), new Reggiano(), mew Garlic() , null)
}
}

This will cause a lot of maintenance headaches!!! Imagine what happens


when we create a new pizza!
We know that we have a certain set of ingredients that are used for New
York..yet we have to keep repeating that set with each constructor. Can we
define this unique set just once??
9/7/2016 4
PizzaIngredientFactory (pg 146)
Create an interface for creating the different ingredients of Pizza.
public interface PizzaIngredientFactory {

public Dough createDough();


public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies(); Note that each
public Pepperoni createPepperoni(); ingredient of Pizza
public Clams createClam(); has a corresponding
method defined in
the interface.
}

9/7/2016 5
NYPizzaIngredientFactory (pg 147)
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {

public Dough createDough() {


return new ThinCrustDough();
}
Here we see the set
public Sauce createSauce() {
of ingredients that
return new MarinaraSauce();
are specific to the NY
}
region.
public Cheese createCheese() {
return new ReggianoCheese();
}
Note that each time a
. . . createXXX() method is
called, a new instance
} is returned. This will
be important later on.

9/7/2016 6
CheesePizza (pg 150)
Instead of many
public class CheesePizza extends Pizza { ingredient parameters,
we just pass one.
PizzaIngredientFactory ingredientFactory;

public CheesePizza(PizzaIngredientFactory ingredientFactory) {


this.ingredientFactory = ingredientFactory;
}

void prepare() {
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce(); Creation
cheese = ingredientFactory.createCheese(); delegated
}
}

Note: Not all


Does this remind you of another pattern?? ingredients have to
be used!
9/7/2016 7
NYPizzaStore (pg 152)
public class NYPizzaStore extends PizzaStore {

protected Pizza createPizza(String item) { The specific


Pizza pizza = null; ingredient factory
is defined once
PizzaIngredientFactory ingredientFactory = for the NY region.
new NYPizzaIngredientFactory();

if (item.equals("cheese")) {
pizza = new CheesePizza(ingredientFactory);
} else if (item.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
} else if (item.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
} else if (item.equals("pepperoni")) {
pizza = new PepperoniPizza(ingredientFactory);
}
return pizza;

9/7/2016 8
Abstract Factory Defined

GoF Intent: “Provides an interface for creating


families of related or dependent objects
without specifying their concrete classes.”

9/7/2016 9
Factory Method vs. Abstract Factory

• Factory Method
– Uses inheritance to create a Concrete Product
– Sub classes decide which Concrete Product to use

• Abstract Factory
– Uses composition to create objects
– The objects created were a part of a family of
objects. For example, NY region had a specific set
of ingredients.
– An abstract factory actually contains one or more
Factory Methods!
9/7/2016 10
Database Example
• Imagine you wanted to created a database manager
object as an enterprise component. This object must
not be tied to a specific database implementation.

• Each specific database uses different objects:


– Connection
– Command
– Adapter
– Data Reader

• Oracle, SQL Server, Informix, etc will have their own


version of these Sub Products.
9/7/2016 11
DatabaseFactory
public abstract class DatabaseFactory
new SqlCommand()
{
new SqlCommand(cmdText)
public abstract IDbCommand CreateCommand();
public abstract IDbCommand CreateCommand(string cmdText);
public abstract IDbCommand CreateCommand(string cmdText, IDbConnection cn);
public abstract IDbConnection CreateConnection();
public abstract IDbConnection CreateConnection(string cnString);
public abstract IDbDataAdapter CreateDataAdapter();
public abstract IDbDataAdapter CreateDataAdapter(IDbCommand selectCmd);
public abstract IDataReader CreateDataReader(IDbCommand dbCmd);
} Viết hai lớp sau:
class SQLDbFactory: DatabaseFactory
class MySQLDbFactory: DatabaseFactory
Each database implementation (Oracle, SQL Server, etc) will need to create
their own version of this DatabaseFactory.

The specific DatabaseFactory must be sent to the constructor of the


framework class DatabaseManager.

Tiếp tục sau 08:10


9/7/2016 12
Abstract Factory and Singleton

• If you have many different Abstract Factories,


you probably just need one instance of each
abstract factory.

• You can use a Singleton to define each


Abstract Factory.

9/7/2016 13
A more interesting case…

What if NY Pizza Store wanted the flexibility to


change their ingredients all the time??

For example, one day use:


– ThickCrust Dough (not Thin)
– Marina Sauce (which was previously used)
– Provolone Cheese (not Reggiano)

And then next week the cheese needs to be


changed to Cheddar (since Provolone shipment
didn’t come in time).
9/7/2016 14
What will happen??

• Class Explosion!

• We would need an Abstract Factory for every


possible combination…and when we add a
new ingredient, we could have to create even
more Abstract Factories.

9/7/2016 15
Solution: Abstract Factory and
Prototype
When we create the abstract factory, pass the
different applicable products in the constructor.

PizzaIngredientFactory ingredientFactory =
new NYPizzaIngredientFactory
(new ThinCrustDough(), new MarinaraSauce(),
new Provolone() );

These products could easily come from an XML


file or even by the user during runtime.

9/7/2016 16
Solution: Abstract Factory and
Prototype
• The abstract factory can then be passed to the different
types of Pizzas.

• When a method is called (ie, createDough,


createSauce), a cloned copy of the Product is returned.
– This ensures that each call to a createXXX method returns
a unique instance.
– Note: In our standard abstract factory, a unique instance is
returned every time you call a createXXX method.

• More information on Prototype


– http://www.oodesign.com/prototype-pattern.html
– Gang of Four (pg 122)

9/7/2016 17
Abstract Factory: Last Thoughts

• This may be a hard pattern to “see” during the


initial design process.

• You may encounter this pattern during


refactoring.

9/7/2016 18
Summary

• Pattern Name – Abstract Factory


• Problem – Need to way to create a family of
products
• Solution
– Create an interface for creating products
• Consequences
– Objects are created using interface
– Composition is used to create objects
– Abstract Factory and Singleton
– Abstract Factory and Prototype

9/7/2016 19

You might also like