Upload
roxanne-hall
View
265
Download
0
Embed Size (px)
Abstract Factory
Abstract Factory using Factory Method
Factory Method
PizzaStoreorderPizza()
SimplePizzaFactorycreatePizza()
Pizzaprepare()bake()cut()box()
CheesePizza
VeggiePizza
ClamPizza
ClamPizza
2
Creating multiple factories
PizzaStore
NYPizzaFactory
ChicagoPizzaFactory
3
Creating Multiple Factories To demonstrate the factory method pattern, the
pizza store example evolves To include the notion of different franchises That exist in different parts of the country (California,
New York, Chicago) Each franchise will need its own factory to create
pizzas that match the tastes of the locals However, we want to retain the creation process that
has made PizzaStore such a great success The Factory Method Design Pattern allows you to
do this by placing abstract, “code to an interface” code in a
superclass placing object creation code in a subclass PizzaStore becomes an abstract class with an abstract
createPizza() method We then create subclasses that override
CreatePizza() for each region4
Changes in PizzaStore
public abstract class PizzaStore
{
Pizza pizza = null;
public abstract Pizza CreatePizza(String type);
public void OrderPizza(String type)
{
pizza = CreatePizza(type);
pizza.Prepare();
pizza.Bake();
pizza.Cut();
pizza.Box();
}//Method of Ordering a Pizza
}5
Concrete Pizza Store Classespublic class NYPizzaStore :
PizzaStore
{
public override Pizza CreatePizza(string type)
{
if (type.Equals("cheese"))
{ return new NYCheesePizza(); }
else if (type.Equals("pepperoni"))
{return new NYPepperoniPizza();}
return null;
}
}
public class ChicagoPizzaStore : PizzaStore {
public override Pizza CreatePizza(String type)
{
if(type.Equals("cheese")) { return new ChicagoCheesePizza();}
else if(type.Equals("pepperoni")) { return new ChicagoPepperoniPizza();}
return null; } }
6
Calling Program
7
class Program { static void Main(string[] args) { //Calling the NY Pizza Store to Order our
Cheese Pizza PizzaStore nypizzastore = new
NYPizzaStore(); nypizzastore.OrderPizza("cheese");
Console.ReadLine(); } }
Allowing the subclasses to decide
PizzaStorecreatePizza()orderPizza()
NYStylePizzaStorecreatePizza()
ChicagoStylePizzaStorecreatePizza()
A factory method CreatePizza() handles object creation and encapsulates it in the subclass. This decouples the client code in the super class from the object creation that happens in the subclass.
8
Pizza Store Franchises
PizzaStorecreatePizza()orderPizza()
NYStylePizzaStorecreatePizza()
ChicagoStylePizzaStorecreatePizza()
Pizza
NYStyleCheesePizzaNYStyleCheesePizza
NYStyleCheesePizzaNYStyleCheesePizza
ChStyleCheesePizzaChStyleCheesePizza
ChStyleCheesePizzaChStyleCheesePizza
Creator Classes
Product Classes
9
Looking at object dependencies
PizzaStore
NyStyleCheezePizza
NyStyleCheezePizza
NyStyleCheezePizza
NyStyleCheesePizza
ChicagoCheezePizza
ChicagoCheezePizza
ChicagoCheezePizza
ChicagoCheesePizza
Because the Pizza Store depends on the concrete implementations any change in concrete classes may change the Pizza Store class
Before Applying Factory Method
10
Design PrincipleDependency Inversion Principle
Depend upon abstractions. Do not depend upon concrete classes.
“High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.”
11
Applying the principle
PizzaStore
NyStyleCheezePizza
NyStyleCheezePizza
NyStyleCheezePizza
NyStyleCheesePizza
ChicagoCheezePizza
ChicagoCheezePizza
ChicagoCheezePizza
ChicagoCheesePizza
Pizza
Pizza is an abstract class
12
Some guidelines to help with the principle Try and avoid having variables that refer to a
concrete class Instead of using new use a factory to achieve this
Try and avoid deriving from a concrete class Derive from an abstract class
Try and avoid overriding an implemented method Could be done if deriving from an abstract class
13
Moving On… The factory method approach to the pizza
store is a big success allowing our company to create multiple franchises across the country quickly and easily
But, bad news, we have learned that some of the franchises while following our procedures (the abstract code
in PizzaStore forces them to) are skimping on ingredients in order to lower costs
and increase margins So what can be done?
14
Abstract Factory to the Rescue! We will alter our design such that a factory is
used to supply the ingredients that are needed during the pizza creation process
Since different regions use different types of ingredients, we’ll create region-specific subclasses of the ingredient factory to ensure that the right ingredients are used
But, even with region-specific requirements, since we are supplying the factories, we’ll make sure that ingredients that meet our quality standards are used by all franchises
But first let us look at what Abstract Factory Pattern is?
15
Intent
Provide an interface for creating families of related or dependent objects without specifying their concrete classes
A.k.a Kit The Abstract Factory pattern is very similar
to the Factory Method pattern One difference between the two is that
with the Abstract Factory pattern, a class delegates the responsibility of object instantiation to another object via composition
Whereas the Factory Method pattern uses inheritance and relies on a subclass to handle the desired object instantiation
16
Motivation Consider a user interface that supports multiple look
and feel standards Different look and feel standards define different
appearances and behaviors of user interface widgets like buttons, windows etc.
The application should not hard code its widgets to a particular look and feel
Using objects of individual look and feel standards makes it hard to change the look and feel later.
This problem can be solved by Abstract Widget Factory class, and abstract classes for each kind of widget.
Concrete classes implement the widgets for a particular look and feel standard
Also enforces dependencies between the concrete classes. 17
Motivation (Cont’d)
Scrollbar*
CreateScrollBar()CreateWindow()
WidgetFactory*
CreateScrollBar()CreateWindow()
MotifWidgetFactory
CreateScrollBar()CreateWindow()
PMWidgetFactory
Client
Window*
MotifWindow
MotifScrollbarPMScrollbar
PMWindow
18
ApplicabilityUse the Abstract Factory pattern when A system should be independent of how its
products are created, composed and represented
A system should be configured with one of multiple families of products
A family of related product objects is designed to be used together, and you need to enforce this constraint.
You want to provide a class library of products, and you want to reveal just their interfaces, not their implementations.
19
Structure
20
Participants Abstract Factory (WidgetFactory)
Declares an interface for operations that create abstract product objects
Concrete Factory (MotifWidgetFactory, PMWidgetFactory) Implements the operations to create concrete product
objects Abstract Product (Window, Scrollbar, Button)
Declares an interface for a type of product object Concrete Product (MotifWindow, MotifScrollbar)
Defines a product to be created by the corresponding concrete factory.
Implements the AbstractProduct interface. Client
uses only interfaces declared by AbstractFactory and AbstractProduct classes.
21
Collaborations
Normally a single instance of a ConcreteFactory class is created at run-time. (This is an example of the Singleton Pattern.) This concrete factory creates product objects having a particular implementation. To create different product objects, clients should use a different concrete factory.
AbstractFactory defers creation of product objects to its ConcreteFactory
22
Consequences Isolates concrete classes
Factory encapsulates the responsibility & process of creating product objects
Makes exchanging product families easy The class of concrete factory appears only once in
the application - that is , where it’s instantiated Promotes consistency among products
Enforces, that products from one family are used together at one time
Supporting new kinds of products is difficult AbstractFactory interface fixes the set of
products that can be created Involves changing AbstractFactory interface
and all its subclasses.23
Implementation Factories can be implemented as singletons Creating the products
Use Factory Method pattern declare FactoryMethod for each kind of
product in AbstractFactory override FactoryMethod in ConcreteFactory
Use Prototype pattern for ConcreteFactory if many product families are possible initialize the concrete factory with a
prototypical instance of each product in the family
concrete factory will create a new product by cloning the prototype
no need for a new concrete factory class for each new family24
Extending the factory pattern… Now we Expand the Pizza store example How are you going to ensure that each franchise
uses quality ingredients We are going to build factory of ingredients which
is going to produce them and ship them to the franchises.
How do we deal with families of ingredients? Chicago: ThickCrust Dough,PlumTomato Sauce,Raggiano
Cheese and Dakin Pepperoni New York: ThinCrust Dough,Mariana Sauce,Mozzarella
Cheese and Sliced Pepperoni Basically, we have got same product families
(Dough, Sauce, Cheese, Pepperoni) but different implementations based on region.25
Building the ingredient factories Lets start by defining interface that is going to
create all our ingredients
public interface PizzaIngredientsFactory { Dough CreateDough(); Sauce CreateSauce(); Cheese CreateCheese(); Pepperoni CreatePepperoni(); }
26
Building Individual Ingredient Interfaces Defining interfaces for individual ingredient
/* Defining Interfaces for our Ingredients like * Dough,Sauce,Cheese,Pepperoni */ public interface Dough{string toString();} public interface Sauce{string toString();} public interface Cheese{string toString();} public interface Pepperoni{string toString();}
27
Building NY ingredient factorypublic class NYPizzaIngredientsFactory : PizzaIngredientsFactory{
public NYPizzaIngredientsFactory() { }
public Dough CreateDough() {
return new ThinCrustDough();
}
public Sauce CreateSauce() {
return new MarianaSauce();
}
public Cheese CreateCheese(){
return new MozzarellaCheese();
}
public Pepperoni CreatePepperoni(){
return new SlicedPepperoni();
}
}
28
Building Chicago ingredient factory
29
public class ChicagoPizzaIngredientsFactory : PizzaIngredientsFactory {
public ChicagoPizzaIngredientsFactory() { }
public Dough CreateDough() {
return new ThickCrustDough();
}
public Sauce CreateSauce() {
return new PlumTomatoSauce();
}
public Cheese CreateCheese() {
return new RaggianoCheese();
}
public Pepperoni CreatePepperoni() {
return new DakinPepperoni();
}
}
Concrete Individual Ingredient Classespublic class ThickCrustDough : Dough
{
public String toString()
{return "ThickCrust style extra thick crust dough";}
}
public class ThinCrustDough : Dough{
public String toString()
{ return "Thin crust dough"; }
}
public class PlumTomatoSauce : Sauce{
public String toString()
{ return "PlumTomato Sauce"; }
}
public class MarianaSauce : Sauce{
public String toString()
{ return "Mariana Sauce"; }}
public class MozzarellaCheese : Cheese{
public String toString()
{ return "Mozzarella Cheese"; }
}
public class RaggianoCheese : Cheese{
public String toString()
{ return "Raggiano Cheese"; }
}
public class SlicedPepperoni : Pepperoni{
public String toString()
{ return "Sliced Pepperoni"; }
}
public class DakinPepperoni : Pepperoni{
public String toString()
{ return "Dakin Pepperoni"; }}
30
Reworking the pizzas (abstract pizza class)
public abstract class Pizza {
protected String name;
protected Dough dough;
protected Sauce sauce;
protected Cheese cheese;
protected Pepperoni pepperoni;
public Pizza() { }
//Declarations of Pizza Funtions
public abstract void Prepare();
public abstract void Bake();
public abstract void Cut();
public abstract void Box();
}
31
Reworking the Pizza Concrete classes
32
When we wrote the Factory method we had four concrete classes of Pizza NYCheesePizza ChicagoCheesePizza NYPepperoniPizza ChicagoPepperoniPizza
Now we don’t need these four classes and the Factory is going to handle the type of pizza for us we would only have two classes now CheesePizza PepperoniPizza
CheesePizza Class
33
public class CheesePizza : Pizza {
PizzaIngredientsFactory ingredientsfactory;
public CheesePizza(PizzaIngredientsFactory ingredientsfactory){
this.ingredientsfactory = ingredientsfactory;
}
public override void Prepare(){
dough = ingredientsfactory.CreateDough();
sauce = ingredientsfactory.CreateSauce();
cheese = ingredientsfactory.CreateCheese();
pepperoni = ingredientsfactory.CreatePepperoni();
Console.WriteLine("Pizza has been Prepared using" + dough.toString() + sauce.toString() + cheese.toString() + pepperoni.toString());
}
public override void Bake() { Console.WriteLine("Baking CHEESE PIZZA"); }
public override void Cut() { Console.WriteLine("Cutting CHEESE PIZZA"); }
public override void Box() { Console.WriteLine("Boxing CHEESE PIZZA"); } }
Reworking the PizzaStore Concrete Classes
34
We will work on the individual Pizza Stores like NY Pizza Store to update them about the relevant ingredients factory
public class NYPizzaStore : PizzaStore {
protected override Pizza CreatePizza(string type){
Pizza pizza = null;
PizzaIngredientsFactory ingredientsFactory = new NYPizzaIngredientsFactory();
if (type.Equals("Cheese"))
{ pizza = new CheesePizza(ingredientsFactory); }
else if (type.Equals("Pepperoni"))
{ pizza = new PepperoniPizza(ingredientsFactory); }
return pizza;
}
Our Calling Program
class Program { static void Main(string[] args) { NYPizzaStore nypizzastore = new
NYPizzaStore(); nypizzastore.OrderPizza("Pepperoni"); Console.ReadLine(); } }
35
Summary: What did we just do?
36
We created an ingredient factory interface to allow for the creation of a family of ingredients for a particular pizza
This abstract factory gives us an interface for creating a family of products The factory interface decouples the client code from
the actual factory implementations that produce context-specific sets of products
Our client code (PizzaStore) can then pick the factory appropriate to its region, plug it in, and get the correct style of pizza (Factory Method) with the correct set of ingredients (Abstract Factory)
ProductA1
Abstract Factory Pattern example
<<Interface>>PizzaIngFactoryCreateDough()
CreateCheese()
ConcreteFactory1
CreateProductA()CreateProductB()
ChicPizzaIngFctry
CreateDough()CreateCheese()
Pizza
<<Interface>>Dough
ThinCrust
<<Interface>>Cheese
NYPizzaIngFctry
CreateDougn()CreateCheese()
Reggiano
ThickCrust
Mozzarella
37
Factory Method used inside Abstract Factory
38
The job of an Abstract Factory is to define an interface for a set of products
Each method in that interface is responsible for creating a concrete product
These methods are normally factory methods, in other words factory methods are a natural way to implement the product methods in the abstract factories