demand
It is required to facilitate the expansion of pizza types and maintenance
- There are many kinds of pizza
- Pizza making includes prepare, bake, cut and box
- 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
- The code is easy to understand
- 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
- 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