23 design patterns-factory pattern [simple factory, factory method, abstract factory]

Series of articles

23 design patterns-the purpose of design patterns and the seven principles to follow
23 design patterns-singleton mode [hungry, lazy, double check, static internal classes, enumeration]
23 design patterns-factory mode [Simple factory, factory method, abstract factory]
23 design modes-prototype mode [clone sheep, shallow copy, deep copy]


2. Factory model

There is such a pizza project demand:

  1. There are many types of pizza, such as GreekPizza, CheessPizza
  2. Pizza making includes prepare, bake, cut, box
  3. Now complete the pizzeria ordering function

According to the traditional way, Pizza must be made into an abstract class first. Pizza contains prepare, bake, cut, and box methods. Different pizzas must be prepared differently, so prepare is an abstract method. GreekPizza and CheessPizza inherit the Pizza class and implement their own methods, while the store that orders pizza will depend on Pizza, CheessPizza and GreekPizza.

But this obviously does not comply with the OCP (opening and closing principle). When we add a new kind of pizza, we will modify the user, because OrderPizza1 will depend on pizza, and generally there is more than one OrderPizza. So we need to optimize it.

1615211902392

 

2.1, simple factory model

  • The simple factory model belongs to the creation model, which is a kind of factory model. The simple factory pattern is determined by a factory object to create an instance of which product class is created. It is the easiest pattern to use in the factory pattern.

  • Simple factory pattern: defines a class for creating objects, and this class encapsulates the behavior i of instantiated objects.

  • In development, when we will use a large number of objects to create a certain, a certain type, or seek to criticize, we must use the factory model.

    1615251451851

Add a SimpleFactory to uniformly produce pizzas. Other orders only need to be handed over to the factory instead of directly relying on Pizza. The factory can return different types of pizzas according to different orders, thus satisfying the principle of opening and closing.

Pizza category

public abstract class Pizza {
    
    
    public abstract void prepare();
    public void bake(){
    
    
        System.out.println("烤披萨");
    }
    public void cut(){
    
    
        System.out.println("切披萨");
    }
    public void box(){
    
    
        System.out.println("装盒");
    }
}

public class CheesePizza extends Pizza {
    
    
    @Override
    public void prepare() {
    
    
        System.out.println("准备奶酪披萨材料");
    }
}

public class GreekPizza extends Pizza {
    
    
    @Override
    public void prepare() {
    
    
        System.out.println("准备希腊披萨材料");
    }
}

Simple factory

public class SimpleFactory {
    
    
    //根据不同订单,返回不同的披萨
    public static Pizza createPizza(String orderType){
    
    
        Pizza pizza = null;

        System.out.println("使用简单工厂模式");
        if (orderType.equals("greek")){
    
    
            System.out.println("希腊披萨");
            pizza = new GreekPizza();
        }
        else if(orderType.equals("cheese")){
    
    
            System.out.println("奶酪披萨");
            pizza = new CheesePizza();
        }
        return pizza;
    }
}

Order class

public class OrderPizza {
    
    
    Pizza pizza = null;

    public OrderPizza(){
    
    
        String orderType = "";
        do{
    
    
            orderType = getType();
            pizza = SimpleFactory.createPizza(orderType);
            if (pizza != null){
    
    
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.bake();
            }
            else{
    
    
                System.out.println("订购披萨失败!");
                break;
            }
        }while (true);
    }


    private String getType(){
    
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入披萨类型:");
        String string = scanner.nextLine();
        if (string != null)
            return string;
        return "";
    }

    public static void main(String[] args) {
    
    

        OrderPizza orderPizza = new OrderPizza();
    }
}

 

2.2. Factory method pattern

Now the pizza project has a new demand: when customers order pizza, they can order different flavors of pizza, such as cheese pizza in Beijing, Greek pizza in Beijing or cheese pizza in London.

Idea 1: We still use the simple factory model, but different regions require us to create multiple factories, such as BJPizzaSimpleFactory and LDPizzaSimpleFactory. However, considering the scale of the project, the maintainability and scalability of the software, this approach is not particularly good.

Idea 2: Use the factory method pattern-postpone the instantiation of the object to the subclass implementation. In the pizza project, the instantiation function of the pizza project is abstracted as an abstract method, which is implemented in different order sub-categories of different flavors.

All four types of pizza inherit from the Pizza class, BJOrder and LDOrder inherit from the abstract class OrderPizza, and createPizza is implemented by a concrete class.

1615253421538

Pizza

//Pizza抽象类
public abstract class Pizza {
    
    
    public abstract void prepare();
    public void bake(){
    
    
        System.out.println("烤披萨");
    }
    public void cut(){
    
    
        System.out.println("切披萨");
    }
    public void box(){
    
    
        System.out.println("装盒");
    }
}

//北京奶酪披萨
public class BJCheesePizza extends Pizza {
    
    
    @Override
    public void prepare() {
    
    
        System.out.println("准备北京奶酪披萨原材料");
    }
}

//北京希腊披萨
public class BJGreekPizza extends Pizza {
    
    
    @Override
    public void prepare() {
    
    
        System.out.println("准备北京希腊披萨原材料\"");
    }
}

//伦敦奶酪披萨
public class LDCheesePizza extends Pizza {
    
    
    @Override
    public void prepare() {
    
    
        System.out.println("准备伦敦奶酪披萨原材料");
    }
}

//伦敦希腊披萨
public class LDGreekPizza extends Pizza {
    
    
    @Override
    public void prepare() {
    
    
        System.out.println("准备伦敦希腊披萨原材料\"");
    }
}

Abstract factory: order abstract class

public abstract class OrderPizza {
    
    
    //抽象方法,具体由子类工厂实现
    public abstract Pizza createPizza(String orderType);

    //抽象类的构造方法,在子类实例化时因为有super(),所以会先被执行。
    public OrderPizza(){
    
    
        Pizza pizza = null;
        String orderType = "";
        do{
    
    
            orderType = getType();
            pizza = createPizza(orderType);//根据子类的不同,返回不同披萨
            if (pizza != null){
    
    
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.bake();
            }
            else{
    
    
                System.out.println("订购披萨失败!");
                break;
            }
        }while (true);
    }

	//获得用户输入的披萨类型
    private String getType(){
    
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入披萨类型:");
        String string = scanner.nextLine();
        if (string != null)
            return string;
        return "";
    }
}

Specific factories in London and Beijing

//北京的订单工厂
public class BJOrderPizza extends OrderPizza {
    
    
    @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 LDOrderPizza extends OrderPizza {
    
    
    @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;
    }
}

test

public class Test {
    
    
    public static void main(String[] args) {
    
    
        //订购北京的披萨
        BJOrderPizza bjOrderPizza = new BJOrderPizza();
        //订购伦敦的披萨
        LDOrderPizza ldOrderPizza = new LDOrderPizza();
    }
}

 

2.3, abstract factory pattern

  • Abstract factory pattern: Define an interface to create a cluster of related or dependent objects without specifying a specific class.
  • The abstract factory pattern can integrate the simple factory and the factory method pattern, which is an improvement of the simple factory pattern.
  • The factory is abstracted into two layers, AbsFactory (abstract factory) and concrete implementation class factory. Programmers use the corresponding factory according to the type of object created, thus turning a single simple factory class into a factory cluster, which is conducive to code maintenance and expansion.

There is a pizza production method in the interface AbsFactory, and BJFactory and LDFactory implement this interface to implement specific methods of producing their own pizzas. Other order classes only need to aggregate with the interface AbsFactory to use the implementation classes BJFactory and LDFactory. This is not the case A single simple factory.

1615

Pizza category (same as before)

Abstract factory and concrete factory

//一个抽象工厂模式的抽象层(接口)
public interface AbsFactory {
    
    
    //由具体的工厂实现类完成
    Pizza creatPizza(String orderType);
}

//工厂子类
public class BJFactory implements AbsFactory {
    
    
    @Override
    public Pizza creatPizza(String orderType) {
    
    
        Pizza pizza = null;
        if (orderType.equals("cheese"))
            pizza = new BJCheesePizza();
        else if (orderType.equals("greek"))
            pizza = new BJGreekPizza();
        return null;
    }
}

//工厂子类
public class LDFactory implements AbsFactory {
    
    
    @Override
    public Pizza creatPizza(String orderType) {
    
    
        Pizza pizza = null;
        if (orderType.equals("cheese"))
            pizza = new LDCheesePizza();
        else if (orderType.equals("greek"))
            pizza = new LDGreekPizza();
        return null;
    }
}

Order class

package design_partten.factory.absfactory;

import java.util.Scanner;

public class OrderPizza {
    
    
    //聚合的方式使用工厂
    AbsFactory absFactory;

    public OrderPizza(AbsFactory absFactory){
    
    
        setAbsFactory(absFactory);
    }
	
    //设置工厂,订购披萨
    private void setAbsFactory(AbsFactory absFactory){
    
    
        Pizza pizza = null;
        String orderType = "";
        this.absFactory = absFactory;
        do {
    
    
            orderType = getType();
            //absFactory可能是北京的工厂子类,也可能是伦敦的工厂子类
            pizza = absFactory.creatPizza(orderType);
            if (pizza != null){
    
    
                pizza.prepare();
                pizza.bake();
                pizza.cut();
                pizza.bake();
            }
            else{
    
    
                System.out.println("订购披萨失败!");
                break;
            }
        }while (true);
    }
	//获取用户输入类型
    private String getType(){
    
    
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入披萨类型:");
        String string = scanner.nextLine();
        if (string != null)
            return string;
        return "";
    }
}

test

public class Test {
    
    
    public static void main(String[] args) {
    
    
        //北京披萨
        new OrderPizza(new BJFactory());
        //伦敦披萨
        new OrderPizza(new LDFactory());
    }
}

 

2.4. Source code of factory mode in JDK-Calendar

Calendar of static method getInstance()to obtain a Calendar instance, when we did not pass because the district and region, and therefore getInstance()will call createCalendar()to use the default time zone and regions.

In this method, our simple factory model is used, similar to the previous pizza order, we give different types of orders, and it will return different pizzas. createCalendar()Return to different Calendars according to different time zones.

Insert picture description here
1615258508474

 

2.5 Summary

  • The significance of the factory model:

    Extract the code of the instantiated object, put it in a factory class for unified management and maintenance, to achieve the decoupling of the main project dependency, thereby improving the scalability and maintainability of the code.

    1615258947650
  • Three factory patterns: simple factory pattern, factory method pattern, abstract factory pattern

  • The abstract principle of design pattern dependence :

    • When creating an object, do not create it directly with new, but put the actions of the new class in the method of the factory class, and the object will be returned by this method.
    • Don't let the class inherit the concrete class, but inherit the abstract class or implement the interface.
    • Do not re-implement methods in the base class.

Guess you like

Origin blog.csdn.net/qq_39763246/article/details/114578285