Factory Mode of Design Mode

Factory Mode

There are three factory modes: simple factory mode, factory method mode, and abstract factory mode.
Let's simulate a pizza scene, different flavors of pizza

Traditional Patterns

First, create an abstract class of pizza, because the raw materials are different, make an abstract pizza, implemented by specific subclasses

public abstract class Pizza {
    protected String name;

    /**
     * Prepare the raw materials and make them abstract because they are different
     */
    public abstract void prepare();

    public void back(){
        System.out.println(name + "back");
    }

    public void cut(){
        System.out.println(name + "cut");
    }

    public void box(){
        System.out.println(name + "box");
    }

    public void setName(String name){
        this.name = name;
    }
}

Two subclass implementations

public class GreekPizza extends Pizza{
    @Override
    public void prepare() {
        System.out.println("Preparing raw materials for Greek pizza");
    }
}
public class CheesePizza extends Pizza{
    @Override
    public void prepare() {
        System.out.println("Preparing to make cheese pizza Preparing raw materials");
    }
}

Order pizza

public class OrderPizza {

    private Pizza pizza ;

    public OrderPizza(){
        this.pizza = null;
        String orderType; // type
        do {
            orderType = getOrderType();
            if (orderType.equals("greek")){
                pizza = new GreekPizza();
                pizza.setName("Greek Pizza");
            }else if (orderType.equals("cheese")){
                pizza = new CheesePizza();
                pizza.setName("Cheese pizza");
            }else {
                break;
            }
            pizza.prepare();
            pizza.back();
            pizza.cut();
            pizza.box();
        }while (true);
    }

    public String getOrderType(){
        try{
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza");
            String str = bufferedReader.readLine();
            return str;
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }
    }
}

Pizza Shop

public class PizzaStore {
    public static void main(String[] args) {
        new OrderPizza();
    }
}

Advantages and disadvantages of traditional methods
1. The advantage is that it is easy to understand and operate.
2. The disadvantage is that it violates the ocp principle of design mode, that is, expanding development to the outside world and closing modifications, that is, when we add new functionality to a class, we try not to modify the code or modify it as little as possible.
Improvement Analysis
Analysis: Modifying the code is acceptable, but if we have code to create Pizza elsewhere, it means that we also need to modify it to create Pizza's code, which is often more than one place
Idea: Encapsulate the creation of Pizza objects into a class so that when we have a new Pizza type, we only need to modify that class, and other code with plug-ins to the Pizza object does not need to be modified - "Simple Factory Mode

Simple Factory Mode

Basic Introduction

  1. Simple factory mode is a creation mode and one of the factory modes. Simple factory mode is an instance of which product class is created by a factory object. Simple factory mode is the simplest and most practical mode in the factory mode family.
  2. Simple Factory Mode: Defines a class that creates objects that encapsulates the behavior (code) of instantiated objects.
  3. In software development, factory mode is used when we use a large number of objects to create a certain, a certain type, or a batch of objects

First let's create a simple factory

public class SimpleFactory {
    /**
     * Returns the corresponding Pizza object based on orderType
     * @param orderType
     * @return
     */
    public Pizza createPizza(String orderType){
        System.out.println("Use simple factory mode");
        Pizza pizza = null;
        if (orderType.equals("greek")){
            pizza = new GreekPizza();
            pizza.setName("Greek Pizza");
        }else if (orderType.equals("cheese")){
            pizza = new CheesePizza();
            pizza.setName("Cheese pizza");
        }
        return pizza;
    }
}

Create a new class to order pizza

public class OrderPizza02 {
    SimpleFactory simpleFactory;
    Pizza pizza = null;

    public OrderPizza02(SimpleFactory simpleFactory){
        setSimpleFactory(simpleFactory);
    }

    public void setSimpleFactory(SimpleFactory simpleFactory){
        String orderType = "";
        this.simpleFactory = simpleFactory;
        do {
            orderType = getOrderType();
            this.pizza = simpleFactory.createPizza(orderType);
            // Output pizza information
            if (pizza != null){
                pizza.prepare();
                pizza.back();
                pizza.cut();
                pizza.box();
            }else {
                System.out.println("Failed to order pizza");
                break;
            }
        }while (true);
    }

    public String getOrderType(){
        try{
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza");
            String str = bufferedReader.readLine();
            return str;
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }
    }
}

Create a new pizza store

public class PizzaStore02 {
    public static void main(String[] args) {
        new OrderPizza02(new SimpleFactory());
        System.out.println("Exit the program");
    }
}

Analysis
With simple factory mode, we don't need to modify too much code. Why? There are more than one pizza store. Traditionally, we need to modify several pizza store classes manually so that we can modify a lot of code. In simple factory mode, we only need to modify the simple factory class.

Factory method

Scene: There were pizzas with different flavors before, and this has been expanded, pizza is not taste, and it's Geographic
Basic Introduction

Design scheme: abstract the instantiation function of pizza project into an abstract method and implement it in different subclasses

Factory Method Mode: Defines an abstract method for creating objects whose subclasses determine which classes to instantiate. Factory Method Mode defers instantiation of objects to subclasses

Pizza's abstract class stays the same, adding its subclasses

public class LDGreekPizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("Preparing raw materials for London Greek pizza");
        setName("London Greek Pizza");
    }
}
public class LDCheesePizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("Preparing to make London cheese pizza Preparing raw materials");
        setName("London cheese pizza");
    }
}
public class BJGreekPizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("Preparing raw materials for Greek pizza in Beijing");
        setName("Greek pizza in Beijing");
    }
}
public class BJCheesePizza extends Pizza {
    @Override
    public void prepare() {
        System.out.println("Preparing to make Beijing cheese pizza Preparing raw materials");
        setName("Beijing cheese pizza");
    }
}

In this case, we will abstract the class ordering pizza, define an abstract method, createPizza method, which is implemented by pizza ordering from different regions
Modified OrderPizza

public abstract class OrderPizza {
    private Pizza pizza ;

    // Define an abstract method, createPizza, for each factory subclass to implement itself
    abstract Pizza createPizza(String orderType);

    public OrderPizza(){
        this.pizza = null;
        String orderType; // type
        do {
            orderType = getOrderType();
            pizza = createPizza(orderType);// Completed by factory subclass
            if (pizza == null){
                break;
            }
            pizza.prepare();
            pizza.back();
            pizza.cut();
            pizza.box();
        }while (true);
    }

    public String getOrderType(){
        try{
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza");
            String str = bufferedReader.readLine();
            return str;
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }
    }
}

Subclass implementation:

public class BJOrderPizza extends OrderPizza{
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")){
            pizza = new BJCheesePizza();
        }else if (orderType.equals("greek")){
            pizza = new BJGreekPizza();
        }
        return pizza;
    }
}
public class LDOrderPizza extends OrderPizza{
    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")){
            pizza = new LDCheesePizza();
        }else if (orderType.equals("greek")){
            pizza = new LDGreekPizza();
        }
        return pizza;
    }
}

At this point, the pizza store just needs to call the implementation of an ordered pizza from the corresponding region.

public class PizzaStore {
    public static void main(String[] args) {
        new BJOrderPizza();
    }
}

Analysis
In this case, we can also use a simple factory, but it is not easy to expand. In order to maintain the system, it is much better to use the abstract factory mode. When expanding, you just need to create the corresponding OrderPizza.

Abstract Factory Mode

Basic Introduction

  1. Abstract Factory Mode: An interface is defined to create a related or dependent object cluster without specifying a specific class
  2. The abstract factory pattern integrates the abstract factory pattern with the factory method pattern
  3. From the design level, abstract factory mode is an improvement (or further abstraction) of simple factory mode.
  4. The factory is abstracted into two layers, ABSFactory (abstract factory) and a concrete implementation of the factory subclass. Programmers can use the corresponding factory subclass based on the type of object they create. This makes it easier to maintain and extend code by turning a single simple factory into a cluster of factories

The pizza code is still there, basically creating the corresponding abstract factory

public interface AbsFactory {
    Pizza createPizza(String orderType);
}

Complete the pizza production process by creating an interface to an abstract factory that is implemented by the corresponding factory class
Realization:

public class BJFactory implements AbsFactory {

    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza =null;
        if (orderType.equals("cheese")){
            pizza = new BJCheesePizza();
        }else if (orderType.equals("greek")){
            pizza = new BJGreekPizza();
        }
        return pizza;
    }
}
public class LDFactory implements AbsFactory{

    @Override
    public Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")){
            pizza = new LDCheesePizza();
        }else if (orderType.equals("greek")){
            pizza = new LDGreekPizza();
        }
        return pizza;
    }
}

In this case, instead of ordering the pizza OrderPizza abstract, we use the factory method to create the corresponding pizza class

public class OrderPizza {

    private AbsFactory factory;

    public OrderPizza(AbsFactory factory){
        setAbsFactory(factory);
    }

    private void  setAbsFactory(AbsFactory factory){
        Pizza pizza = null;
        String orderType = "";
        this.factory = factory;
        do {
            orderType = getOrderType();
            pizza = factory.createPizza(orderType);
            if (pizza == null){
                break;
            }
            pizza.prepare();
            pizza.back();
            pizza.cut();
            pizza.box();
        }while (true);
    }

    private String getOrderType(){
        try{
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza");
            String str = bufferedReader.readLine();
            return str;
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }
    }

}

Analysis
The abstract factory pattern takes a step further and creates the original Pizza creation process from the corresponding factory, in which the extension can be accomplished by simply creating the corresponding factory class

summary

In general, the factory mode is to adapt to the expansion of programs in different modes, reduce code modifications, create corresponding objects, and improve development efficiency

Tags: Design Pattern

Posted on Sun, 12 Sep 2021 00:12:35 -0400 by runthis