Abstract factory pattern

Posted by pauls74462 on Thu, 10 Feb 2022 15:18:15 +0100

I. Introduction of models

The factory method mode considers the production of a kind of products, such as TV factory only produces TV, pizza shop only produces pizza, etc.

Similar products are called the same grade, that is to say: the factory method mode only considers the production of products of the same grade, but in real life, many factories are comprehensive factories that can produce products of multiple grades (types). For example, both animals and plants are raised on the farm, and KFC produces hamburgers and fried chicken.

Abstract factory pattern is an upgraded version of factory method pattern. Factory method pattern only produces one level of products, while abstract factory pattern can produce multiple levels of products. A group of products at different levels produced by the same specific factory is called a product family, as shown in the following figure: the corresponding relationship between televisions and air conditioners generated by Haier factory and TCL factory.

1.1 definition

The abstract factory pattern provides an interface for creating families of related or interdependent objects without specifying the specific class of the product to be produced.

The following conditions are generally met when using abstract factory mode:

  1. There are multiple product families in the system. Each specific factory creates products of the same family but belonging to different hierarchical structures
  2. The system can only consume the products of one family at a time, that is, the products of the same family can be used together.

1.2 advantages

  1. It has the advantages of factory mode
  2. The multi-level products associated in the product family can be managed together within the class, instead of introducing multiple new classes for management
  3. When a product family is needed, the abstract factory can ensure that the client always uses the product family of the same product
  4. Abstract factory enhances the scalability of the program. When adding a new product family, there is no need to modify the source code and meet the opening and closing principle

1.3 disadvantages

  1. When a new product needs to be added to the product family, all factory classes need to be modified
  2. It increases the abstraction and understanding difficulty of the system

2, Structure and Implementation

2.1 structure

Abstract factory mode, like factory method mode, is also composed of four elements: abstract factory, concrete factory, abstract product and concrete product. However, the number of methods in abstract factory is different, so is the number of abstract products.

  1. Abstract factory: it provides an interface for creating products. It contains multiple methods for creating products newProduct(), which can create multiple products of different levels.
  2. Concrete factory: it mainly realizes the abstract methods in the abstract factory and completes the creation of specific products.
  3. Abstract Product: it defines the specification of the Product and describes the main characteristics and functions of the Product. The abstract factory has multiple Abstract products.
  4. Concrete product: it implements the interface defined by the abstract product role and is created by the specific factory. It corresponds to the specific factory one by one.

2.2 realization

2.2.1 class diagram

2.2.2,NYPizzaStore

package com.erlang.factory.abstract_;


/**
 * @description: New York Pizza
 * @author: erlang
 * @since: 2022-02-08 22:28
 */
public class NYPizzaStore extends PizzaStore {

    @Override
    protected Pizza createPizza(String type) {
        Pizza pizza = null;
        PizzaIngredientFactory factory = new NYPizzaIngredientFactory();
        if (type.equals("cheese")) {
            pizza = new CheesePizza(factory);
            pizza.setName("NY Style Cheese Pizza");
        } else if (type.equals("clam")) {
            pizza = new ClamPizza(factory);
            pizza.setName("NY Style Clam Pizza");
        }
        return pizza;
    }
}

2.2.3,PizzaIngredientFactory

package com.erlang.factory.abstract_;

/**
 * @description: Chicago pizza ingredients processing factory
 * @author: erlang
 * @since: 2022-02-09 22:38
 */
public interface PizzaIngredientFactory {
    /**
     * dough
     *
     * @return dough
     */
    Dough createDough();

    /**
     * sauce
     * @return
     */
    Sauce createSauce();
}

2.2.4,NYPizzaIngredientFactory

package com.erlang.factory.abstract_;

/**
 * @description: New York Pizza
 * @author: erlang
 * @since: 2022-02-09 22:59
 */
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {

    @Override
    public Dough createDough() {
        return new ThinCrustDough("Thin Crust Dough");
    }

    @Override
    public Sauce createSauce() {
        return new MarinaraSauce("Marinara Sauce");
    }
}

2.2.5,ChicagoPizzaIngredientFactory

package com.erlang.factory.abstract_;

/**
 * @description: Chicago pizza
 * @author: erlang
 * @since: 2022-02-09 22:39
 */
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {

    @Override
    public Dough createDough() {
        return new ThickCrustDough("Extra Thick Crust Dough");
    }

    @Override
    public Sauce createSauce() {
        return new PlumTomatoSauce("Plum Tomato Sauce");
    }
}

2.2.6,Dough

package com.erlang.factory.abstract_;

/**
 * @description: Dough interface
 * @author: yj
 * @since: 2022-02-09 22:42
 */
public interface Dough {

    /**
     * dough
     *
     * @return Return to dough
     */
    String getDough();
}

2.2.7,ThickCrustDough

package com.erlang.factory.abstract_;

/**
 * @description:
 * @author: erlang
 * @since: 2022-02-09 22:53
 */
public class ThickCrustDough implements Dough {

    private String dough;

    public ThickCrustDough(String dough) {
        this.dough = dough;
    }

    @Override
    public String getDough() {
        return dough;
    }
}

2.2.8,ThinCrustDough

package com.erlang.factory.abstract_;

/**
 * @description:
 * @author: erlang
 * @since: 2022-02-09 22:57
 */
public class ThinCrustDough implements Dough {

    private String dough;

    public ThinCrustDough(String dough) {
        this.dough = dough;
    }

    @Override
    public String getDough() {
        return dough;
    }
}

2.2.9,Sauce

package com.erlang.factory.abstract_;

/**
 * @description:
 * @author: erlang
 * @since: 2022-02-09 22:44
 */
public interface Sauce {

    /**
     * sauce
     *
     * @return sauce
     */
    String getSauce();
}

2.2.10,PlumTomatoSauce

package com.erlang.factory.abstract_;

/**
 * @description:
 * @author: erlang
 * @since: 2022-02-09 22:55
 */
public class PlumTomatoSauce implements Sauce {

    private String sauce;

    public PlumTomatoSauce(String sauce) {
        this.sauce = sauce;
    }

    @Override
    public String getSauce() {
        return sauce;
    }
}

2.2.11,MarinaraSauce

package com.erlang.factory.abstract_;

/**
 * @description:
 * @author: erlang
 * @since: 2022-02-09 22:57
 */
public class MarinaraSauce implements Sauce {

    private String sauce;

    public MarinaraSauce(String sauce) {
        this.sauce = sauce;
    }

    @Override
    public String getSauce() {
        return sauce;
    }
}

2.2.12,CheesePizza

package com.erlang.factory.abstract_;

/**
 * @description: Cheese pizza
 * @author: erlang
 * @since: 2022-02-08 21:23
 */
public class CheesePizza extends Pizza {

    PizzaIngredientFactory ingredientFactory;

    public CheesePizza(PizzaIngredientFactory ingredientFactory) {
        this.ingredientFactory = ingredientFactory;
    }

    @Override
    public void prepare() {
        System.out.printf("Preparing %s Pizza\n", name);
        dough = ingredientFactory.createDough();
        sauce = ingredientFactory.createSauce();
    }
}

Topics: Design Pattern