preface

The creation pattern is mainly used to solve the creation problem of Java objects

The factory pattern

Description of the factory pattern

In object-oriented programming, the concepts of inheritance and polymorphism implement the (IS-A) relationship between superclasses and subclasses

Based on this relationship, subclass polymorphism is implemented. This abstract approach provides the same operation for subclasses and supports the functional extension of subclasses. But this is a problem, right?

Verhicle verhicle = new Car();

Verhicle verhicle = new Truck();

The problem is:

  1. A subclass overrides a parent class’s methods, so when a subclass instantiates a parent object, it must do so for each subclass. This causes different constructors to be called for different subclasses to instantiate the superclass object. Lack of unified operation.
  2. In addition, it can be seen from the above two lines of code that the dependency between subclass and parent class, high degree of coupling
  3. It violates the parent open and close principle and the subclass single responsibility principle

The introduction of simple factory pattern, the implementation of logic encapsulation, the use of a common factory class to achieve the unified creation of object instantiation parent class behavior.

Simple Factory model

  • There are three ways to implement simple factories
    1. Static factory mode
    2. Use reflection for class registration
    3. Use the newInstance method for class registration

A UML diagram of a simple factory

  • Static factory mode solution:

Create a separate Verhicle simple factory class. The built-in enumeration stores all subclasses that need to create instances, and the unified Create (type) method creates instances on demand based on the type of the argument passed in.

public class VerhicleFactory { public enum VerhicleType { Car,Truck,Boat; } public static Verhicle create(VerhicleType type) { if(type.equals(VerhicleType.Car)) { return new Car(); } if(type.equals(VerhicleType.Truck)) { return new Truck(); } if(type.equals(VerhicleType.Boat)) { return new Boat(); } else return null; }}Copy the code

Advantage:

This additional use of factory classes overcomes the principle of breaking the single responsibility for instantiating the parent class of the subclass above, and implements the unified operation of constructing instances.

Disadvantages:

As you can see from the stored enumeration, any new extended subclass must modify the factory enumeration, breaking the factory class’s own open and close principle.

There is still no solution to the open and close principle of the parent class closing inside and expanding outside.

  • A solution to class registration using reflection

To solve the problem of static factory mode breaking its own open and close principles, we can use reflection to make registered new classes instantiated at use. Thus to ensure the external development, internal modification closed. That is, the enumeration in the static factory does not have to be modified even if you add a subclass that extends the parent class.

Public class Product1 extends Product {} public class Product1 extends Product {} public class Product1 extends Product {} public class Product1 extends Product {} More extended subclasses... */ public class MoreProducts extends Product {} / private Map<String, class > registeredProduct = new  HashMap<String,Class>(); /** all extended subclasses will be recorded in the Map collection *@parameter * productId subclass ID is the type of the subclass, corresponding to static factory enumeration type * productClass subclass class object, Public void registerProduct(String productId, Class productClass) {registeredProduct. Put (productId, Class productClass) {registeredProduct. productClass); } /** take the subclass type passed in, construct the corresponding instance of the subclass, and return *@parameter * ProductType as the subclass ID above, Corresponding static factory enumerated type * / public Product createProduct (String ProductType) throws InstantiationException, IllegalAccessException { Class productClass = registeredProduct.get(ProductType); return (Product) productClass.newInstance(); } // The client will register the class and create the instance according to the corresponding methodCopy the code

Advantages:

It solves the problem that static factory classes break the open and close principle by separating registration from instance creation.

Disadvantages:

Reflection affects program performance, and with more use, program performance becomes much less efficient.

  • A simple factory pattern for class registration using the newInstance method

Just a minor modification to the idea of class registration based on the reflection mechanism above:

  1. Avoid reflection to improve performance
  2. How do you do that?
    • The Map collection does not store Class objects, but instances of subclasses that have been created
  • Create an abstract method in the base class
  • Subclass all override, method body is to create the subclass object
    • This implements the subclass instance already created when stored in the Map collection above
Public abstract class {Product newInstance(); } public class Product1 extends Product {} /*... More extended subclasses... */ public class MoreProducts extends Product { @override public MoreProducts newInstance() { return new MoreProducts(); Private Map<String,Product> registeredProduct = new HashMap<String,Product>(); /** all extended subclasses will be recorded in the Map collection *@parameter * productId subclass ID is the type of the subclass, corresponding to static factory enumeration type * productClass subclass class object, Public void registerProduct(String productId, Product productType) {registeredProduct.put(productId, productType); productType); } /** take the subclass type passed in, construct the corresponding instance of the subclass, and return *@parameter * ProductType as the subclass ID above, Corresponding static factory enumerated type * / public Product createProduct (String ProductId) throws InstantiationException, IllegalAccessException { Product productType = registeredProduct.get(ProductId); return (Product) productType.newInstance(); } // The client will register the class and create the instance according to the corresponding methodCopy the code

Advantages:

Abstract classes are divided between base classes, which solves the open and close principle of parent class and the single responsibility principle of subclass. Supports uniform operations for creating objects.

Disadvantages:

Inheritance relationships between classes cause problems with code that remains highly coupled.

There is still a risk that the parent class is not implemented for internal modification closure.

Factory method pattern

UML diagram of the factory method pattern

Solution:

  1. The server interface to the product, for all products that need to be expanded can directly achieve unified interface methods, as well as custom methods.

  2. In addition, the abstract factory can integrate the service function of the product into the abstract factory, and the abstract method of constructing the instance is built in. The factory classes of all extension products can then inherit and implement the corresponding constructors and functions.

// sever public interface Product{ void features(); } public class implements Product {/* Implements Product {/* implements Product {/* implements Product {/* implements Product Public abstract class AbastractFactory {Product create(); Public class implements AbstractFactory {/* implements AbstractFactory */} public class implements AbstractFactory {/* implements AbstractFactory */} public class implements AbstractFactory MoreProductsFactory extends AbstractFactory {/* Implement constructor */}Copy the code

Advantage:

The products are decoupled, and each extension product has a corresponding factory class that implements the corresponding construction instances and service functions

Disadvantages:

Easy to cause the redundancy of the factory, the expansion of too many products when the factory category increased.

Abstract Factory pattern

Solutions:

Instead of creating a single unified constructor in an abstract factory based on the factory method pattern, one or all of the extended product constructors are created. In this way, factory class inheritance only needs less inheritance to complete the construction tasks of multiple extension products.

// sever public interface Product{ void features(); } public class implements Product {/* Implements Product {/* implements Product {/* implements Product {/* implements Product Public abstract Class AbastractFactory {Product createProduct1(); // define Product1 constructor Product createMoreProducts(); Public class ProductFactory extends AbstractFactory {public class ProductFactory extends AbstractFactory {public class ProductFactory extends AbstractFactory {Copy the code

Advantages:

Reduce the number of factory classes and avoid redundancy

The last

Welcome to pay attention to the public number: the future has light, receive a line of large factory Java interview questions summary + the knowledge points learning thinking guide + a 300 page PDF document Java core knowledge points summary!