Java Interview Process Manual (Java Learning Guide, welcome Star, will continue to improve, welcome suggestions and guidance) : github.com/Snailclimb/…

Historical review:

Understand singleton patterns in depth

Historical articles recommended:

The classical fundamental theory of distributed systems

Probably the most beautiful explanation of Spring transaction management

This is enough interview questions about the Java Virtual Machine (JVM)

[TOC]

Factory model introduction

1.1 Definition of factory mode

Let’s look at the definition of GOF as a factory pattern:

“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to Subclasses. “Define an interface for creating objects in the base class and let subclasses decide which class to instantiate. The factory method lets instantiation of a class be deferred to subclasses.

1.2 Classification of factory mode:

(1) Simple Factory Pattern, also known as Static Factory Method Pattern.

(2) The Factory Method pattern, also called Polymorphic Factory pattern or Virtual Constructor pattern;

(3) Abstract Factory mode, also known as Kit or Toolkit mode.

1.3 Use in open source frameworks

Two common examples (I can think of exactly what’s going on right now, but there are many, many more):

(1) In Spring, get the Bean from getBean(” XXX “);

(2) Java message service JMS (take Message queue ActiveMQ as an example below)

The usage of Message queue ActiveMQ can be seen in detail: Usage of Message queue ActiveMQ


 	// Create a connection factory object. Specify the IP address and port of the service.
	ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("TCP: / / 192.168.25.155:61616");
		// create a Connection object using the factory object.
		Connection connection = connectionFactory.createConnection();

Copy the code

1.4 Why factory mode

(1) Decoupling: Separate the creation and use of objects

(2) Reduce code duplication: If the process of creating an object is complicated and requires a certain amount of code, and it needs to be used in many places, there will be a lot of repeated code.

(3) Reduce maintenance costs: Since the creation process is uniformly managed by the factory, business logic changes do not need to find all places where an object needs to be created to correct one by one, but only need to modify in the factory to reduce maintenance costs.

An article about the role of the factory pattern, Mark: blog.csdn.net/lovelion/ar…

Simple factory model

2.1 introduction

Strictly speaking, the simple factory pattern is not one of the 23 commonly used design patterns; it is only a special implementation of the factory pattern. The simple factory pattern is still used much less in practice than the other two factory patterns, because it only applies to many simple cases.

Most importantly, it violates the open-closed principle we discussed in the overview (although it can be avoided through the mechanism of reflection, which we’ll cover later). Because every time you add a new function, you need to modify the code in the switch-case statement (or if-else statement) to add a branch condition.

2.2 Application Scenarios

(1) Fewer objects need to be created.

(2) The client does not care about the object creation process.

2.3 Role Assignment in Simple Factory Mode:

  1. Factory role: The core of the simple Factory pattern, which is responsible for implementing the internal logic that creates all instances. The factory class can be called directly from the outside world to create the desired product object.
  2. Abstract Product role: The parent class of all objects created by the simple factory pattern, which is responsible for describing the common interface shared by all instances.
  3. Concrete Product role: The creation target of the simple factory pattern, where all created objects are instances of a Concrete class that acts as this role.

2.4 Simple factory example

Create a drawing tool that can draw different shapes. You can draw circles, squares, triangles, and each shape will have a draw() method for drawing.

(1) Create Shape interface


public interface Shape {
	void draw(a);
}
Copy the code

(2) Create a concrete graphics class to implement the interface

circular


public class Circle implements Shape {
    public Circle(a) {
		System.out.println("Circle");
	}
	@Override
	public void draw(a) {
		System.out.println("Draw Circle"); }}Copy the code

A rectangle


public class Rectangle implements Shape {
    public Rectangle(a) {
		System.out.println("Rectangle");
	}
	@Override
	public void draw(a) {
		System.out.println("Draw Rectangle"); }}Copy the code

A square


public class Square implements Shape {
	public Square(a) {
		System.out.println("Square");
	}

	@Override
	public void draw(a) {
		System.out.println("Draw Square"); }}Copy the code

(3) Create factory class:


public class ShapeFactory {

	// Use getShape to get an object of the shape type
	public static Shape getShape(String shapeType) {
		if (shapeType == null) {
			return null;
		}
		if (shapeType.equalsIgnoreCase("CIRCLE")) {
			return new Circle();
		} else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
			return new Rectangle();
		} else if (shapeType.equalsIgnoreCase("SQUARE")) {
			return new Square();
		}
		return null; }}Copy the code

(4) Test method:


public class Test {

	public static void main(String[] args) {

		// Get the Circle object and call its draw method
		Shape circle = ShapeFactory.getShape("CIRCLE");
		circle.draw();

		// Get the Rectangle object and call its draw method
		Shape rectangle = ShapeFactory.getShape("RECTANGLE");
		rectangle.draw();

		// Get the Square object and call its draw method
		Shape square = ShapeFactory.getShape("SQUARE"); square.draw(); }}Copy the code

Output result:

Circle
Draw Circle
Rectangle
Draw Rectangle
Square
Draw Square

Copy the code

The problem with this implementation is that if we add a new product class, we need to modify the getShape () method in the factory class, which clearly does not comply with the open-closed principle.

2.5 Use reflection to improve simple factories

Change the factory class to the following form:

package factory_pattern;

/** * Use reflection to solve the problem that simple factories need to modify product factories every time a new product class is added **@author Administrator
 *
 */
public class ShapeFactory2 {
	public static Object getClass(Class<? extends Shape> clazz) {
		Object obj = null;

		try {
			obj = Class.forName(clazz.getName()).newInstance();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		returnobj; }}Copy the code

Test method:

package factory_pattern;

public class Test2 {
	public static void main(String[] args) { Circle circle = (Circle) ShapeFactory2.getClass(factory_pattern.Circle.class); circle.draw(); Rectangle rectangle = (Rectangle) ShapeFactory2.getClass(factory_pattern.Rectangle.class); rectangle.draw(); Square square = (Square) ShapeFactory2.getClass(factory_pattern.Square.class); square.draw(); }}Copy the code

Although this approach conforms to the open-close principle, but each pass is the entire path of the product class, which is more troublesome. If it needs to be improved, it can be improved in the form of reflection + configuration file, which is more commonly used.

3. Factory method mode

3.1 introduction

The factory method pattern should be the most used pattern in the factory pattern family, and it is the pattern that exists most in a typical project.

The factory method pattern is a step further from the simple factory. Instead of providing a single factory class to create all objects, we provide different factories for different objects. That is, each object has a factory corresponding to it.

3.2 Application Scenarios

  • A class does not know the class of the object it needs: in the factory method pattern, the client does not need to know the class name of the specific product class, only the corresponding factory. The specific product object is created by the specific factory class. The client needs to know the factory class to create the specific product.
  • A class specifies which object to create by subclass: in the factory method pattern, an abstract factory class only needs to provide an interface to create a product, and its subclass determines which object to create, using object-oriented polymorphism and Richter’s method
  • Delegate the task of creating an object to one of the factory subclasses. The client can use the factory subclass to create a product subclass without worrying about which factory subclass is used, and specify it dynamically when necessary. The class name of the specific factory class can be stored in the configuration file or database.

3.3 Role assignment in factory Method Mode:

  1. Abstract Factory role: Is the core of the Factory method pattern and is application-independent. The factory class of any object created in the schema must implement this interface.
  2. Concrete Factory role: This is a Concrete Factory class that implements an abstract Factory interface, contains application-specific logic, and is called by the application to create some kind of product object.
  3. AbstractProduct role: A supertype of an object created by a factory method pattern, that is, a common parent or jointly owned interface of the product object.
  4. Concrete Product role: This role implements the interface defined by the abstract Product role. A specific product is created in a specific factory, often with a one-to-one correspondence between them

3.4 Factory method pattern instance

The graphical interface and associated image implementation classes in the simple factory example above remain unchanged. We just need to add a factory interface and a factory class that implements that interface.

(1) Add a factory interface:

public interface Factory {
	public Shape getShape(a);
}

Copy the code

(2) Add related factory categories:

Circular factory class

public class CircleFactory implements Factory {

	@Override
	public Shape getShape(a) {
		// TODO Auto-generated method stub
		return newCircle(); }}Copy the code

Rectangular factory class

public class RectangleFactory implements Factory{

	@Override
	public Shape getShape(a) {
		// TODO Auto-generated method stub
		return newRectangle(); }}Copy the code

Circular factory class

public class SquareFactory implements Factory{

	@Override
	public Shape getShape(a) {
		// TODO Auto-generated method stub
		return newSquare(); }}Copy the code

(3) Test:

public class Test {

	public static void main(String[] args) {
		Factory circlefactory = newCircleFactory(); Shape circle = circlefactory.getShape(); circle.draw(); }}Copy the code

Output result:

Circle
Draw Circle

Copy the code

Abstract factory pattern

4.1 introduction

In the factory method pattern, we actually have a consciousness of latent consciousness. We all produce the same kind of product. The abstract factory pattern is a step further of the factory approach, in which a factory class can create not just one product, but a set of products.

Abstract factory is one of the most difficult factory patterns to understand.

4.2 Application Scenarios

  • Like the factory method, the client does not need to know the class of the object it is creating.
  • When a group of objects is required to perform some function together, and there may be multiple groups of objects performing different functions. (Products belonging to the same product family)
  • The system structure is stable and objects are not added frequently. (Because the original code needs to be modified once it is added, which is inconsistent with the open and close principle)

4.3 Abstract Factory Method Mode role allocation:

  1. AbstractFactory role: The core of the factory method pattern, application-independent. The factory class of any object created in the schema must implement this interface.
  2. The ConreteFactory role: This is a concrete factory class that implements an abstract factory interface, contains application-specific logic, and is called by the application to create a product object.
  3. Abstract Product role: A supertype of an object created by the factory method pattern, that is, a common parent or jointly owned interface of the Product object.
  4. Concrete Product Role: Any Product object created by the abstract factory pattern is an instance of a Concrete Product class. Products created in an abstract factory belong to the same product family, as opposed to factories that create a single product, as I’ll explain later.

.

4.4 What is the difference between the abstract factory factory and the factory method?

An abstract factory is a factory that produces a set of products (at least two products) that must be related or dependent on each other, whereas a factory in the factory method is a factory that produces a single product.

4.5 Abstract factory pattern instance

I don’t know if you’ve played crossfire or Chicken, but there are all kinds of guns. Let’s say there are two types of guns, AK and M4A1, each with a bullet. So the way we think about it now is that the factory that makes the AK can make the bullets that the AK uses, and the factory that makes the M4A1 can make the bullets that the M4A1 uses. (AK factory produces AK series products including bullets and types of AK guns, the same as M4A1 factory)

(1) Create relevant interfaces:

The gun

public interface Gun {
	public void shooting(a);
}

Copy the code

The bullet

public interface Bullet {
	public void load(a);
}
Copy the code

(2) Create the corresponding implementation class of the interface:

AK class

public class AK implements Gun{

	@Override
	public void shooting(a) {
		System.out.println("shooting with AK"); }}Copy the code

M4A1 class

public class M4A1 implements Gun {

	@Override
	public void shooting(a) {
		System.out.println("shooting with M4A1"); }}Copy the code

AK bullet class

public class AK_Bullet implements Bullet {

	@Override
	public void load(a) {
		System.out.println("Load bullets with AK"); }}Copy the code

M4A1 bullet class

public class M4A1
_Bullet implements Bullet {

	@Override
	public void load(a) {
		System.out.println("Load bullets with M4A1"); }}Copy the code

(3) Create factory interfaces

public interface Factory {
	public Gun produceGun(a);
	public Bullet produceBullet(a);
}

Copy the code

(4) Create specific factories

A factory that produces AK and AK bullets

public class AK_Factory implements Factory{

	@Override
	public Gun produceGun(a) {
		return new AK();
	}

	@Override
	public Bullet produceBullet(a) {
		return newAK_Bullet(); }}Copy the code

The factory that produces M4A1 and M4A1 bullets

public class M4A1_Factory implements Factory{

	@Override
	public Gun produceGun(a) {
		return new M4A1();
	}

	@Override
	public Bullet produceBullet(a) {
		return newM4A1_Bullet(); }}Copy the code

(5) Test

public class Test {

	public static void main(String[] args) {  
		
	 Factory factory;
	 Gun gun;
     Bullet bullet;
     
     factory =newAK_Factory(); bullet=factory.produceBullet(); bullet.load(); gun=factory.produceGun(); gun.shooting(); }}Copy the code

Output result:

Load bullets with AK
shooting with AK

Copy the code

I’m Snailclimb, a little white guy with a 5-year goal to be an architect. Welcome to follow my wechat public account :”Java Interview Clearance Manual “(a warm wechat public account, looking forward to common progress with you ~~~ adhere to the original, share beautiful articles, share a variety of Java learning resources)

Finally, after using Ali Cloud server for a period of time, I felt that Ali Cloud is really good, so I applied to be the Ambassador of Ali Cloud, and this is my coupon address.