1 Simple factory pattern

1.1 Look at a specific requirement

Look at a pizza project: easy to expand the variety of pizza, easy to maintain

  1. There are many types of pizza (such as Greekpizz, Cheesepizz, etc.).
  2. Pizzas are prepared, baked, cut, and box.
  3. Complete the pizza place ordering function.

1.2 Do it the traditional way

  1. Analysis of Ideas (Class Diagram)
  2. Write OrderPizza.java to order the various pizzas you need
// When a new Pizza class is added, OrderPizza needs to be modified. When many classes use OrderPizza, they are subject to a number of modifications. public class OrderPizza { public static void main(String[] args) { new OrderPizza(); } // public OrderPizza() {Pizza Pizza = null; String orderType; // Order the type of pizza 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.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } while (true); } private String getType() {try {BufferedReader in = new BufferedReader(new) InputStreamReader(System.in)); System.out.println("input pizza type: "); return in.readLine(); } catch (Exception e) { e.printStackTrace(); return ""; } } } public abstract class Pizza { protected String name; // Prepare the raw materials for different pizzas. Public Abstract void prepare(); public Abstract void prepare(); public void bake() { System.out.println(name + " baking;" ); } public void cut() { System.out.println(name + " cuting;" ); } public void box() { System.out.println(name + " boxing;" ); } public void setName(String name) { this.name = name; } public class Cheesepizza extends Pizza{@Override public void prepare() {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(" GreekPizza extends Pizza "); }}

1.3 Advantages and disadvantages of traditional methods

  1. Advantages are relatively easy to understand, simple and easy to operate.
  2. The disadvantage is that it violates the OCP principle of design patterns, which is open for extension and closed for modification. That is, when we add new functionality to a class, we try to change the code as little as possible, or as little as possible.
  3. For example, when we want to add a new type of Pizza (Pepper Pizza), we need to make the following modifications. If we add a Pizza class, all the code for ordering Pizza needs to be changed.

1.4 Analysis of improvement ideas

Analysis: It’s okay to change the code, but if we have the Pizza creation code somewhere else, that means we need to change it too, and the Pizza creation code often has multiple places.

The idea is to encapsulate the Pizza object in a class, so that when we have a new Pizza class, we only need to change the class, and other code to create the Pizza object does not need to change. -> simple factory mode

1.5 Basic introduction of simple factory mode

  1. The simple factory pattern belongs to the creation pattern, which is a kind of factory pattern. The simple factory pattern allows a factory object to decide which instance of a product class to create. The simple factory pattern is the simplest and most practical pattern in the factory pattern family.
  2. Simple factory pattern: Defines a class for creating objects that encapsulates the behavior (code) of instantiating objects. The details of creating classes are no longer handed over to the use classes, but rather to the factory classes.
  3. In software development, we use the factory pattern when we need to create a large number of objects, a class, or a batch of objects.

1.6 Use the simple factory mode

The design of the simple factory pattern: Define a class that can instantiate a Pizaa object, encapsulating the code that creates the object.



Code example:

Public class SimpleFactory {// OrderType returns the corresponding Pizza object. The user does not need proof of relationship to create Pizza object details. 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 CheesePizza(); Pizza.setname (" cheese pizza "); } return pizza; } // The simple factory pattern is also called the static factory pattern. Public static Pizza createPizza2(String OrderType) {Pizza Pizza = null; System.out.println(" Use simple factory pattern 2"); 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; }}

Simple factory to use: OrderPizza does not have to make any changes when it adds a new Pizza class.

Public class OrderPizzA2 {private simpleFactory simpleFactory; private Pizza pizza = null; Public OrderPizzA2 (simpleFactory simpleFactory) {setFactory(simpleFactory); } public void setFactory(SimpleFactory simpleFactory) { String orderType = ""; // User-entered this.simpleFactory = simpleFactory; // Set the simple factory object do {orderType = getType(); pizza = this.simpleFactory.createPizza(orderType); // output pizza if (pizza! = null) {// Pizza.prepare (); pizza.bake(); pizza.cut(); pizza.box(); } else {System.out.println(" Failed to order pizza "); break; } } while (true); } // Write a method, Private String getType() {try {BufferedReader in = new BufferedReader(new) InputStreamReader(System.in)); System.out.println("input pizza type :"); String str = in.readLine(); return str; } catch (IOException e) { e.printStackTrace(); return ""; } } public static void main(String[] args) { new OrderPizza2(new SimpleFactory()); }}

2 Factory method pattern

2.1 Look at a new requirement

New requirement of pizza project: when customers order pizza, they can order different pizza flavors, such as cheese pizza in Beijing, pepper pizza in Beijing or cheese pizza in London, pepper pizza in London.

  1. Idea 1: Using the simple factory pattern, create different simple factory classes, such as BJPizzaImpleFactory, LDPizzaImpleFactory, and so on. From the current case, it is also possible, but considering the scale of the project, as well as the software maintainability, scalability is not particularly good
  2. Idea 2: Use the factory method pattern

2.2 Factory method model introduction

  1. Factory method pattern design scheme: abstract the instantiation function of the pizza project into abstract methods, which are implemented in different taste ordering subclasses.
  2. Factory method pattern: Defines an abstract method for creating objects, with subclasses deciding which classes to instantiate. The factory method pattern delays the instantiation of objects to subclasses.

2.3 Application cases of factory method pattern

  1. New requirement of pizza project: when customers order pizza, they can order different pizza flavors, such as cheese pizza in Beijing, pepper pizza in Beijing or cheese pizza in London, pepper pizza in London.
  2. Thought analysis diagram
  3. Code implementation
// public abstract class MethodFactory {// Define an abstract method, CreatePizza, allowing each factory subclass to implement abstract Pizza CreatePizza (String OrderType); // public methodFactory () {Pizza Pizza; String orderType; // Order the type of pizza do {orderType = getType(); pizza = createPizza(orderType); Pizza.prepare (); pizza.prepare(); pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } while (true); } // Write a method, Private String getType() {try {BufferedReader in = new BufferedReader(new) InputStreamReader(System.in)); System.out.println("input pizza type :"); String str = in.readLine(); return str; } catch (IOException e) { e.printStackTrace(); return ""; }}}

Create Pizza related to Beijing tastes:

public class BJPizzaFactory extends MethodFactory { @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; }}

Create London Taste Related Pizza:

public class LDPizzaFactory extends MethodFactory { @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; }}
public abstract class Pizza { protected String name; // Prepare the raw materials for different pizzas. Public Abstract void prepare(); public Abstract void prepare(); public void bake() { System.out.println(name + " baking;" ); } public void cut() { System.out.println(name + " cuting;" ); } public void box() { System.out.println(name + " boxing;" ); } public void setName(String name) { this.name = name; } public class BJCheesepizza extends Pizza {@Override public void prepare() {System.out.println(" ");} public class BJCheesepizza extends Pizza {@Override public void prepare() {System.out.println("); }}

The user uses the corresponding Pizza:

Public class OrderPizza {public static void main(String[] args) {// Pizza new BjpizzaFactory (); }}

3 Abstract factory pattern

3.1 Basic introduction

  1. Abstract Factory pattern: An Interface is defined to create clusters of objects that are related or dependent on each other, without specifying a specific class.
  2. The abstract factory pattern integrates the simple factory pattern with the factory method pattern.
  3. From a design level, the abstract factory pattern is an improvement (or further abstraction) on the simple factory pattern.
  4. The factory is abstracted into two layers, the absFactory (abstract factory) and the factory subclass of the concrete implementation. The programmer can use the corresponding factory subclass depending on the type of object being created. This turns a single simple factory class into a factory cluster, which is easier to maintain and extend the code.
  5. Class diagram:

3.2 Application examples of abstract factory pattern

Use abstract factory mode to complete the pizza project:

Public interface absFactory {// Make the factory subclass Pizza CreatePizza (String OrderType) {// Make the factory subclass Pizza CreatePizza (String OrderType); }

Subclass of Beijing Factory:

Public class BJFactory implements absFactory {@Override public Pizza CreatePizza (String OrderType) {// Override public Pizza CreatePizza (String OrderType) { System.out.println("~ is using the abstract factory pattern ~"); Pizza pizza = null; if (orderType.equals("cheese")) { pizza = new BJCheesePizza(); } else if (orderType.equals("greek")) { pizza = new BJGreekPizza(); } return pizza; }}

Subcategory of London plant:

public class LDFactory implements AbsFactory { @Override public Pizza createPizza(String orderType) { System.out.println("~ is using the abstract factory pattern ~"); Pizza pizza = null; if (orderType.equals("cheese")) { pizza = new LDCheesePizza(); } else if (orderType.equals("greek")) { pizza = new LDGreekPizza(); } return pizza; }}

Pizza:

public abstract class Pizza { protected String name; // Prepare the raw materials for different pizzas. Public Abstract void prepare(); public Abstract void prepare(); public void bake() { System.out.println(name + " baking;" ); } public void cut() { System.out.println(name + " cuting;" ); } public void box() { System.out.println(name + " boxing;" ); } public void setName(String name) { this.name = name; } public class BJCheesepizza extends Pizza {@Override public void prepare() {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 BJGreekPizza extends Pizza {@Override public void prepare() {System.out.println(" "); }}

Factory used:

public class OrderPizza { private AbsFactory factory; // public OrderPizza(absFactory Factory) {setFactory(Factory); } private void setFactory(AbsFactory factory) { Pizza pizza; String orderType = ""; // The user enters this.factory = factory; do { orderType = getType(); // Factory may be a subclass of Pizza = Factory.createPizza (OrderType); if (pizza ! = null) { pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); } else {System.out.println(" Order failed "); break; } } while (true); } // Write a method, Private String getType() {try {BufferedReader in = new BufferedReader(new) InputStreamReader(System.in)); System.out.println("input pizza type :"); return in.readLine(); } catch (IOException e) { e.printStackTrace(); return ""; } } public static void main(String[] args) { new OrderPizza(new BJFactory()); }}

4. The source code analysis of factory mode in JDK-Calendar application

  1. In the Calendar class in the JDK, the simple factory pattern is used
  2. Source analysis +Debug source + description
  3. Simple factory pattern:

5 Factory mode summary

  1. The meaning of the factory pattern is to extract the code of the instantiated object and put it into a class for unified management and maintenance, so as to achieve decoupling from the dependency of the main item. This improves project scalability and maintainability.
  2. Three factory patterns (simple factory pattern, factory method pattern, abstract factory pattern)
  3. When creating an object instance, you don’t create a new class directly. Instead, you put the action of the new class in a factory method and return it. Some books say that variables should not directly hold references to concrete classes.

Instead of a class inheriting a concrete class, it inherits an abstract class or implements an interface.

Do not overwrite methods that are already implemented in the base class.