---
# System prepended metadata

title: 'Design Pattern --- (4) Factory method Pattern , (5) Abstract Factory Pattern'
tags: [Design Pattern, Java, 教學]

---

Design Pattern --- (4) Factory method Pattern , (5) Abstract Factory Pattern
===

## Under what circumstances will the factory method pattern be used?
* A class cannot anticipate the type of objects it needs to create beforehand.

For example:
I have a suepr-class Animal and a ton of sub-classes like dog,cat,duck,etc. So I want to create an animal object but I don't know which sub-classes to be instantiated before the run time. In other words,I am able to dynamically select the type at the run time.

* You want to localize the logic to instantiate a complex object.

For example:
EU and NA both have the cheese pizza,yet they taste are different,the relation diagram is :
![Pizza](https://imgur.com/1HxuZag.jpg "berforepizza" =400x500)
But I can improve the complex relationships to make them more flexible:
![Pizza](https://imgur.com/Ibubkkq.jpg "afterpizza" =400x500)

## How does they implement in code?
As per above situation,suppose I have the Pizza interface ,which has two subclass,cheese pizza and seafood pizza.In addition,there are two pizza store selling them but the taste is different.

```java
abstract class PizzaStore
{
    public abstract Pizza create(String taste);
    public Pizza order(String taste)
    {
        //create
        Pizza pizza = create(taste);
        
        //do something
        pizza.prepare();
        pizza.cook();
        return pizza;
    }
}
class NAPizzaStore extends PizzaStore
{
    public Pizza create(String taste)
    {
        if(taste.equals("cheese"))
            return new NACheesePizza();
        else if(taste.equals("seafood"))
            return new NASeafoodPizza();
        return null;
    }
}
class EUPizzaStore extends PizzaStore
{
    public Pizza create(String taste)
    {
        if(taste.equals("cheese"))
            return new EUCheesePizza();
        else if(taste.equals("seafood"))
            return new EUSeafoodPizza();
        return null;
    }
}
Interface Pizza
{
    void prepare();
    Pizza cook();
}
public class client 
{
    public static void main(String[] arg )
    {
        NYPizzaStore NYPS = new NYPizzaStore();
        NYPS.order("cheese");
        NYPS.order("seafood");
        
        EUPizzaStore NYPS = new EUPizzaStore();
        EUPS.order("cheese");
        EUPS.order("seafood");
    }
}
```

--- 

## What is the relationship between the factory method pattern and the abstract factory pattern ?

The abstract factory pattern actually is a set of the factory methods,so an abstract factory makes use of multiple factory methods.

## Under what circumstances will the abstract factory pattern be used?

An output of a factory depends on several factories.

For example:
Creating a pizza has to add a lot of ingredients like dough,sauce,etc,and each ingredients need a factory to output.
Here is a code without using abstract factory to complete.
↓↓↓
```java=
class NAPizzaStore extends PizzaStore
{
    NADoughFactory DF;
    NASauceFactory SF;
    NACheeseFactory CF;
    NAClamFactory CLF;
    public Pizza create(String taste)
    {
        if(taste.equals("cheese"))
            return new NACheesePizza(DF,SF,CF);
        else if(taste.equals("seafood"))
            return new NASeafoodPizza(DF,SF,CLF);
        return null;
    }
}
class NACheesePizza extends Pizza
{
    NADoughFactory DF;
    NASauceFactory SF;
    NACheeseFactory CF;
    public NACheesePizza(NADoughFactory DF,NASauceFactory SF,NACheeseFactory CF)
    {
        this.DF =DF;
        this.SF =SF;
        this.CF =CF;
    }
    public void prepare()
    {
        dough = DF.create();
        sauce = SF.create();
        cheese = CF.create();
    }
}
class EUPizzaStore extends PizzaStore
{
    EUDoughFactory DF;
    EUSauceFactory SF;
    EUCheeseFactory CF;
    EUClamFactory CLF;
    public Pizza create(String taste)
    {
        if(taste.equals("cheese"))
            return new EUCheesePizza(DF,SF,CF);
        else if(taste.equals("seafood"))
            return new EUSeafoodPizza(DF,SF,CLF);
        return null;
    }
}
```

Obviously,this code is almost unmaintainable,so the abstract factory will come into play.

## How does they implement in code?

The concept is that I build a large abstract factory to manage the above-mentionted several ingredients factories.

```java=
abstract class IngredientsFactory 
{
    public abstract Dough createDough();
    public abstract Sauce createSauce();
    public abstract Cheese createCheese();
    public abstract Clam createClam();
}
class NAIngredientsFactory extends IngredientsFactory
{
    public Dough createDough()
        return new NADough();
    public Sauce createSauce()
        return new NASauce();
    public Cheese createCheese()
        return new NACheese;
    public Clam createClam()
        return new NAClam();
}
class NAPizzaStore extends PizzaStore
{
    NAIngredientsFactory NAIF = new NAIngredientsFactory();
    
    public Pizza create(String taste)
    {
        if(taste.equals("cheese"))
            return new NACheesePizza(NAIF);
        else if(taste.equals("seafood"))
            return new NASeafoodPizza(NAIF);
        return null;
    }
}

class NACheesePizza extends Pizza
{
    NAIngredientsFactory NAIF;
    public CheesePizza(NAIngredientsFactory NAIF)
    {
        this.NAIF = NAIF;
    }
    public void prepare()
    {
        dough = NAIF.createDough();
        sauce = NAIF.createSauce();
        cheese = NAIF.createCheese();
    }
}
class EUIngredientsFactory extends IngredientsFactory
{
    public Dough createDough()
        return new EUDough();
    public Sauce createSauce()
        return new EUSauce();
    public Cheese createCheese()
        return new EUCheese;
    public Clam createClam()
        return new EUClam();
}
class EUPizzaStore extends PizzaStore
{
    EUIngredientsFactory EUIF = new EUIngredientsFactory();
    
    public Pizza create(String taste)
    {
        if(taste.equals("cheese"))
            return new CheesePizza(EUIF);
        else if(taste.equals("seafood"))
            return new SeafoodPizza(EUIF);
        return null;
    }
}
class EUCheesePizza extends Pizza
{
    EUIngredientsFactory EUIF;
    public EUCheesePizza(EUIngredientsFactory EUIF)
    {
        this.EUIF = EUIF;
    }
    public void prepare()
    {
        dough = EUIF.createDough();
        sauce = EUIF.createSauce();
        cheese = EUIF.createCheese();
    }
}
public class client 
{
    NAPizzaStore NAPS = new NAPizzaStore();
    Pizza cheesepizza = NAPS.order("cheese");
    Pizza seafoodpizza = NAPS.order("seafood");
    
    EUPizzaStore EUPS = new EUPizzaStore();
    Pizza cheesspizza = EUPS.order("cheese");
    Pizza seafoodpizza = EUPS.order("seafood");
}
```

## Conclusion

The factory method and abstract factory both have the same keyword "defer".The former defers the instantiation from the super-class to the sub-classes and the latter defers the implementation of a set of factories to the sub-classes.

## Reference
* Chris
https://www.youtube.com/watch?v=EcFVTgRHJLM&t=1s
https://www.youtube.com/watch?v=v-GiuMmsXj4

https://blog.techbridge.cc/2017/05/22/factory-method-and-abstract-factory/

###### tags: `Design Pattern` `Java` `教學`



