Factory mode of design mode

Keywords: Java Design Pattern

demand

It is required to facilitate the expansion of pizza types and maintenance

  1. There are many kinds of pizza
  2. Pizza making includes prepare, bake, cut and box
  3. Complete pizza shop ordering function

Traditional way

Class diagram

code

/**
 * @Classname Pizza
 * @Description
 * @Date 2021/9/28 14:12
 * @Author Yzx
 */
public class Pizza {

    private String name;

    void prepare(){
        System.out.println(name + " Pizza preparation");
    }
    void bake(){
        System.out.println(name + " Pizza baking");
    }
    void cut(){
        System.out.println(name + " Pizza cutting work");
    }
    void box(){
        System.out.println(name + " Pizza cartoning");
    }

    public String getName() {
        return name;
    }

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

}

/**
 * @Classname GreenPizza
 * @Description
 * @Date 2021/9/28 14:34
 * @Author Yzx
 */
public class GreekPizza extends Pizza{

}

/**
 * @Classname CheesePizza
 * @Description
 * @Date 2021/9/28 14:36
 * @Author Yzx
 */
public class CheesePizza extends Pizza{

}

/**
 1. @Classname OrderPizza
 2. @Description
 3. @Date 2021/9/28 14:37
 4. @Author Yzx
 */
public class OrderPizza {

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

    public OrderPizza() {

        Pizza pizza = null;
        String orderType; //  Type of pizza ordered
        do {
            orderType = getType();
            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;
            }
            //Output pizza production process
            pizza.prepare();
            pizza.bake();
            pizza.cut();
            pizza.box();

        } while (true);
    }

    /**
     * Get the type of pizza the customer wants to order
     * @return type
     */
    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

Advantages and disadvantages

  1. The code is easy to understand
  2. It violates the principle of opening the design pattern to the outside world and closing the modification. When we add new functions to the class, we try not to modify the code or reduce the amount of modification as much as possible
  3. When a pizza category needs to be added, the code for ordering pizza needs to be modified

improvement

Encapsulate the creation of pizza objects into a class. When there are new types, you only need to modify this class, and other codes that create pizza objects do not need to be modified, that is, simple factory mode

Simple factory

A factory object determines which product instance to create, which is the simplest pattern used in the factory pattern

Class diagram

code

/**
 * @Classname Pizza
 * @Description
 * @Date 2021/9/28 14:12
 * @Author Yzx
 */
public class Pizza {

    private String name;

    void prepare(){
        System.out.println(name + " Pizza preparation");
    }
    void bake(){
        System.out.println(name + " Pizza baking");
    }
    void cut(){
        System.out.println(name + " Pizza cutting work");
    }
    void box(){
        System.out.println(name + " Pizza cartoning");
    }

    public String getName() {
        return name;
    }

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

}

/**
 * @Classname CheesePizza
 * @Description
 * @Date 2021/9/28 14:36
 * @Author Yzx
 */
public class CheesePizza extends Pizza {

}

/**
 * @Classname GreenPizza
 * @Description
 * @Date 2021/9/28 14:34
 * @Author Yzx
 */
public class GreekPizza extends Pizza {

}

/**
 * @Classname SimpleFactory
 * @Description
 * @Date 2021/9/28 15:29
 * @Author Yzx
 */
public class SimpleFactory {

    public static Pizza createPizza(String orderType) {
        Pizza pizza = null;

        System.out.println("Use simple factory mode");
        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;
    }

}

/**
 * @Classname OrderPizza
 * @Description
 * @Date 2021/9/28 14:37
 * @Author Yzx
 */
public class OrderPizza {

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

    public OrderPizza() {
        //User entered
        String orderType = "";
        Pizza pizza = null;
        do {
            orderType = getType();
            pizza = SimpleFactory.createPizza(orderType);
            //Output pizza
            if (pizza != null) {
                //Order succeeded
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println(" Failed to order pizza ");
                break;
            }
        } while (true);
    }

    /**
     * Get the type of pizza the customer wants to order
     *
     * @return type
     */
    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

Factory method model

New demand

When ordering pizza, customers can order pizza with different flavors, such as cheese pizza in Beijing, pepper pizza in Beijing or cheese pizza in London

thinking

Use the simple factory mode to create different simple factory classes. When there are many local flavors, the maintainability and scalability of the software are not good. You can use the factory method mode

Class diagram

code

/**
 * @Classname Pizza
 * @Description
 * @Date 2021/9/28 14:12
 * @Author Yzx
 */
public class Pizza {

    private String name;

    void prepare(){
        System.out.println(name + " Pizza preparation");
    }
    void bake(){
        System.out.println(name + " Pizza baking");
    }
    void cut(){
        System.out.println(name + " Pizza cutting work");
    }
    void box(){
        System.out.println(name + " Pizza cartoning");
    }

    public String getName() {
        return name;
    }

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

}

/**
 * @Classname BJCheessPizza
 * @Description
 * @Date 2021/9/28 17:20
 * @Author Yzx
 */
public class BJCheesePizza extends Pizza{
    public BJCheesePizza() {
        this.setName("Beijing");
    }
}

/**
 * @Classname BJPepperPizza
 * @Description
 * @Date 2021/9/28 17:20
 * @Author Yzx
 */
public class BJPepperPizza extends Pizza{
    public BJPepperPizza() {
        this.setName("Beijing");
    }
}

/**
 * @Classname BJOrderPizza
 * @Description
 * @Date 2021/9/28 17:23
 * @Author Yzx
 */
public class BJOrderPizza extends OrderPizza {

    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new BJCheesePizza();
        } else if (orderType.equals("pepper")) {
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}

/**
 * @Classname BJCheessPizza
 * @Description
 * @Date 2021/9/28 17:20
 * @Author Yzx
 */
public class LDCheesePizza extends Pizza{
    public LDCheesePizza() {
        this.setName("London");
    }
}

/**
 * @Classname BJPepperPizza
 * @Description
 * @Date 2021/9/28 17:20
 * @Author Yzx
 */
public class LDPepperPizza extends Pizza{
    public LDPepperPizza() {
        this.setName("London");
    }
}

/**
 * @Classname BJOrderPizza
 * @Description
 * @Date 2021/9/28 17:23
 * @Author Yzx
 */
public class LDOrderPizza extends OrderPizza {

    @Override
    Pizza createPizza(String orderType) {
        Pizza pizza = null;
        if (orderType.equals("cheese")) {
            pizza = new LDPepperPizza();
        } else if (orderType.equals("pepper")) {
            pizza = new LDPepperPizza();
        }
        return pizza;
    }
}

/**
 * @Classname OrderPizza
 * @Description
 * @Date 2021/9/28 14:37
 * @Author Yzx
 */
public abstract class OrderPizza {

    public static void main(String[] args) {
        new BJOrderPizza();
        //new LDPepperPizza();
    }

    /**
     * Create pizza
     * @param orderType
     * @return
     */
    abstract Pizza createPizza(String orderType);

    public OrderPizza() {

        Pizza pizza = null;
        String orderType; //  Type of pizza ordered
        do {
            orderType = getType();
            pizza = createPizza(orderType);
            if (pizza != null) {
                //Order succeeded
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println(" Failed to order pizza ");
                break;
            }

        } while (true);
    }

    /**
     * Get the type of pizza the customer wants to order
     * @return type
     */
    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

Abstract factory

Abstract factory pattern is an improvement of simple factory pattern, which can integrate simple factory pattern and factory method pattern
The factory is abstracted into two layers, the abstract factory and the factory subclass of concrete implementation. The corresponding factory subclass can be used according to the created object type to turn a single simple factory class into a factory cluster, which is convenient for code maintenance and expansion

Class diagram

code

/**
 * @Classname Pizza
 * @Description
 * @Date 2021/9/28 14:12
 * @Author Yzx
 */
public class Pizza {

    private String name;

    void prepare(){
        System.out.println(name + " Pizza preparation");
    }
    void bake(){
        System.out.println(name + " Pizza baking");
    }
    void cut(){
        System.out.println(name + " Pizza cutting work");
    }
    void box(){
        System.out.println(name + " Pizza cartoning");
    }

    public String getName() {
        return name;
    }

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

}

/**
 * @Classname BJCheessPizza
 * @Description
 * @Date 2021/9/28 17:20
 * @Author Yzx
 */
public class BJCheesePizza extends Pizza {
    public BJCheesePizza() {
        this.setName("Beijing");
    }
}

/**
 * @Classname BJPepperPizza
 * @Description
 * @Date 2021/9/28 17:20
 * @Author Yzx
 */
public class BJPepperPizza extends Pizza {
    public BJPepperPizza() {
        this.setName("Beijing");
    }
}

/**
 * @Classname BJCheessPizza
 * @Description
 * @Date 2021/9/28 17:20
 * @Author Yzx
 */
public class LDCheesePizza extends Pizza {
    public LDCheesePizza() {
        this.setName("London");
    }
}

/**
 * @Classname BJPepperPizza
 * @Description
 * @Date 2021/9/28 17:20
 * @Author Yzx
 */
public class LDPepperPizza extends Pizza {
    public LDPepperPizza() {
        this.setName("London");
    }
}

/**
 * @Classname AbsFactory
 * @Description
 * @Date 2021/9/29 14:30
 * @Author Yzx
 */
public interface AbsFactory {
    Pizza createPizza(String orderType);
}

/**
 * @Classname BJOrderPizza
 * @Description
 * @Date 2021/9/28 17:23
 * @Author Yzx
 */
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("pepper")) {
            pizza = new BJPepperPizza();
        }
        return pizza;
    }
}

/**
 * @Classname BJOrderPizza
 * @Description
 * @Date 2021/9/28 17:23
 * @Author Yzx
 */
public class LDFactory implements AbsFactory {

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

/**
 * @Classname OrderPizza
 * @Description
 * @Date 2021/9/28 14:37
 * @Author Yzx
 */
public class OrderPizza {

    public static void main(String[] args) {
        new OrderPizza(new BJFactory());
        //new OrderPizza(new LDFactory());
    }


    public OrderPizza(AbsFactory factory) {

        Pizza pizza = null;
        String orderType; //  Type of pizza ordered
        do {
            orderType = getType();
            pizza = factory.createPizza(orderType);
            if (pizza != null) {
                //Order succeeded
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.box();
            } else {
                System.out.println(" Failed to order pizza ");
                break;
            }

        } while (true);
    }

    /**
     * Get the type of pizza the customer wants to order
     * @return type
     */
    private String getType() {
        try {
            BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("input pizza type:");
            String str = strin.readLine();
            return str;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

Summary

Significance of factory model

The instantiated objects are extracted and put into a class for unified management and maintenance, so as to decouple the dependency relationship with the main project, so as to improve the scalability and maintainability of the project

Design patterns rely on abstract principles

  • When creating an object instance, do not directly the new class, but put the action of the new class into a factory method and return. Variables do not directly hold the reference of a specific class
  • Don't let classes inherit concrete classes, abstract classes or implement interfaces
  • Do not override methods already implemented in the base class

Posted by ibechane on Tue, 23 Nov 2021 01:46:42 -0800