Explain the pizza ordering project through a practical case (the factory is actually a pizza factory) |
---|
- It is convenient for pizza variety expansion and maintenance
- There are many kinds of pizza (green pizza, cheese pizza, etc.)
- Pizza making includes prepare, bake, cut and box
- Complete pizza shop ordering function
1. Factory design mode
1. Simple factory mode (divided into static factory and ordinary factory)
A factory is a factory that produces specific objects. No matter how the objects you produce change in the future, the factory only needs to know, and users don't need to pay attention. Suppose one factory and 1000 users, we only need to change the factory code instead of the code of 1000 users to change the objects in the future |
---|
Static factory: the method of producing objects is static |
Ordinary factory: the method of producing objects is not static |
Class diagram: class diagram location: com/yzpnb/design_mode/factory/easy_factory/tradition/Pizza.puml |
---|
The code is at: COM / yzpnb / design_ mode/factory/easy_ Under the factory / tradition package |
---|
- Operation effect
- It violates the ocp principle of design pattern, that is, it is not open to extension and closed to modification. When we add new functions to the class, we should try to ensure that users use your product without modifying or modifying the code less.
- Analyze the problem (the following code determines what kind of pizza the user wants, and then executes the corresponding logic. When we add a class, the following code also needs to be changed)
- The problem is serious. Here, the order class uses this code. Suppose a new class is needed to discount different types of pizza. Then you need to copy the code.
- Suppose we add another class at this time, then the code of both classes needs to be changed
- In the actual development, there are often dozens or even hundreds of classes
How to improve it, we need to use the factory mode |
---|
- Simple factory mode is the simplest and most practical mode in factory mode, in which a factory object determines which product class instance to create
- Define a class to create an object, which encapsulates the behavior of the instance object
- In software development, factory mode is used when a large number of objects, classes or batches need to be created
Improved class diagram: com/yzpnb/design_mode/factory/easy_factory/improved/Pizza.puml |
---|
- Because of the existence of the factory class, when we add a type, we only need to let the factory know. The OrderPizza class does not need to be changed
All codes are at: com/yzpnb/design_mode/factory/easy_factory/improved / |
---|
- Abstract class Pizza
//Abstract the Pizza class
public abstract class Pizza {
protected String name;//name
//Preparing raw materials is different from Pizza, so it is made into an abstract method
public abstract void prepare();
//baking
public void bake(){
System.out.println(name+" baking;");
}
//cutting
public void cut(){
System.out.println(name+" cutting;");
}
//Packing
public void box(){
System.out.println(name+" boxing");
}
public void setName(String name){
this.name = name;
}
}
- Cheese pizza
public class CheessPizza extends Pizza {
@Override
public void prepare() {
System.out.println("Add cheese pizza raw materials!!!");
}
}
- Greek pizza
public class GreekPizza extends Pizza {
@Override
public void prepare() {
System.out.println("Add Greek pizza raw materials!!!");
}
}
- Factory class
import com.yzpnb.design_mode.factory.easy_factory.improved.pizza.CheessPizza;
import com.yzpnb.design_mode.factory.easy_factory.improved.pizza.GreekPizza;
import com.yzpnb.design_mode.factory.easy_factory.improved.pizza.Pizza;
public class SimpleFactory {
//Building Pizza objects
public 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 CheessPizza();
pizza.setName(" Cheese pizza ");
}
return pizza;
}
//Simple factory mode is also called static factory mode
//Make the method of obtaining the object static
public static Pizza createPizza2(String orderType) {
Pizza pizza = null;
System.out.println("Use simple factory mode 2");
if (orderType.equals("greek")) {
pizza = new GreekPizza();
pizza.setName(" Greek pizza ");
} else if (orderType.equals("cheese")) {
pizza = new CheessPizza();
pizza.setName(" Cheese pizza ");
}
return pizza;
}
}
- Order (the static method of factory class is used here, and the static factory is used)
import com.yzpnb.design_mode.factory.easy_factory.improved.factory.SimpleFactory;
import com.yzpnb.design_mode.factory.easy_factory.improved.pizza.Pizza;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class OrderPizza2 {
Pizza pizza = null;
String orderType = "";
// constructor
public OrderPizza2() {
do {
orderType = getType();
pizza = SimpleFactory.createPizza2(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);
}
// Write a method to get the type of pizza customers want to order
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 "";
}
}
}
- pizzeria
import com.yzpnb.design_mode.factory.easy_factory.improved.factory.SimpleFactory;
import com.yzpnb.design_mode.factory.easy_factory.improved.order.OrderPizza;
import com.yzpnb.design_mode.factory.easy_factory.improved.order.OrderPizza2;
/**
* Improved version, using factory mode
*/
public class PizzaShop {
public static void main(String[] args) {
//OrderPizza orderPizza = new OrderPizza(new SimpleFactory());
OrderPizza2 orderPizza2 = new OrderPizza2();
}
}
2. Factory method mode
Suppose we have a new demand. When customers order pizza, they can order pizza from different places, such as cheese pizza in Beijing or cheese pizza in London |
---|
- Scheme 1: use the simple factory mode to create different simple factory classes, such as Beijing pizza simplefactory or London pizza simplefactory. Although it is feasible, considering the future project scale, the maintainability and scalability of the software are not good.
- Scheme 2: use factory method mode
- Define an abstract method to create an object, and the subclass determines the class to be instantiated. The factory method pattern defers instantiation of objects to subclasses
- The instantiation function of pizza project is abstracted into abstract methods and implemented in different taste ordering subclasses
- Generally speaking, the General Factory specifies the production process (abstract method), and sub factories such as Beijing are responsible for making pizza (realizing the abstract method) according to the process specified by the general factory. If users want pizza, they need it directly with sub factories such as Beijing (not in contact with the general factory). After the sub factories make it, they can finally be delivered by the parent factory
- We can simply produce pizza objects from the child factory, and the remaining methods are called by the parent factory
Class diagram: com/yzpnb/design_mode/factory/method_factory/Pizza.puml |
---|
Code: COM / yzpnb / design_ mode/factory/method_ Factory / pizza store package |
---|
- Operation effect
- How to abstract a method factory? (the child factory is the production object, and the parent factory is responsible for performing operations, such as cutting, packing, shipping, etc.)
- How to use?
3. Abstract factory mode (key)
- Abstract factory pattern: define an interface to create clusters of related or dependent objects without specifying specific classes
- Abstract factory pattern can integrate simple factory pattern and factory method pattern
- At the design level, the abstract factory pattern is the improvement (or further abstraction) of the simple factory pattern
- The factory is abstracted into two layers, AbsFactory (Abstract Factory) and the factory subclass of concrete implementation. Programmers can use the corresponding factory subclasses according to the created object types, so as to turn a single simple factory into a factory cluster, which is more conducive to code maintenance and expansion
To sum up, we place an order and directly specify that the order is from London or some other factory. You can directly operate and give me the corresponding pizza, such as London |
---|
- The London factory will create pizza according to the regulations of the general factory
Class diagram: com/yzpnb/design_mode/factory/absfactory/Pizza.puml |
---|
Code: com/yzpnb/design_mode/factory/absfactory package |
---|
- Define abstract factory interface
//Abstract layer (Interface) of abstract factory pattern
public interface AbsFactory {
//Abstract method, concrete implementation of sub factory
public Pizza createPizza(String orderType);
}
- Sub factory (implementation abstract method, production object)
//Sub factory
public class BJFactory implements AbsFactory{
@Override
public Pizza createPizza(String orderType) {
System.out.println("Abstract factory pattern, Beijing Sub factory");
Pizza pizza = null;
if(orderType.equals("cheese")){
pizza = new BJCheesePizza();
}else{
pizza = new BJPepperPizza();
}
return pizza;
}
}
//Sub factory
public class LDFactory implements AbsFactory{
@Override
public Pizza createPizza(String orderType) {
System.out.println("Abstract factory pattern, London sub factory");
Pizza pizza = null;
if(orderType.equals("cheese")){
pizza = new LDCheesePizza();
}else{
pizza = new LDPepperPizza();
}
return pizza;
}
}
- Order, use the specified factory to produce the object, and process the object
public abstract class OrderPizza {
AbsFactory factory;
/**
* Constructor, passing in factory
* @param factory Specify the factory and create the corresponding object
*/
public OrderPizza(AbsFactory factory){
setFactory(factory);
}
//You need to import the factory by yourself
private void setFactory(AbsFactory factory){
Pizza pizza = null;
String orderType = "";//User input
this.factory = factory;
do{
orderType = getType();
pizza = factory.createPizza(orderType);
if(pizza!=null){
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}else{
System.out.println("Subscription failed");
break;
}
}while(true);
}
private String getType() {
try {
BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));
System.out.println("input pizza :");
String str = strin.readLine();
return str;
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}
- Designated London plant, production object
2. Which factory design patterns are used in the Java source code
The Calendar class of java JDK uses a static simple factory |
---|
- Class diagram: com/yzpnb/design_mode/factory/source_analysis/Calendar.puml
- analysis
- Get objects through static methods
- Call the create object method according to whether the time zone and region are passed in, and use the default value without passing
- Create an object method. If the time zone and region are the default values, directly return the instance of provide instead of the default. Select different factories to return the instance of provide according to your region and time zone