DoF 23 (design mode) - > single case mode, factory mode

Singleton mode

characteristic:

  1. Ensure that a class has only one instance and provide a global access point to access the instance.
  2. A singleton class must create its own unique instance.
  3. A singleton class must provide this instance to all other objects.
  4. Singleton pattern constructors, instances are private.

The singleton pattern ensures that a class has only one instance, and instantiates itself and provides this instance to the whole system. In short, the singleton pattern is to avoid inconsistent states.

1, Lazy loading mode

//The lazy singleton class instantiates itself at the first call
public class Singleton{
	private Singleton(){}
	//It will be created first, but will not be instantiated, but will be instantiated when called.
	private static Singleton single = null;
	//Static factory method
	public static Singleton getInstance(){
		if(single == null){
			single = new Singleton();
		}
		return single;
	}
}

Singleton prevents the class from being instantiated externally by limiting the construction method to private. Within the scope of the same virtual machine, the only instance of singleton can only be accessed through (an external interface) getInstance() method.
(in fact, a class whose constructor is private can be instantiated through the java reflection mechanism, that is, the constructor and properties private to the singleton pattern can be obtained, which will basically invalidate all Java singleton implementations.)

The implementation of lazy Singleton does not consider thread safety. It is thread unsafe in the case of multithreading. Multiple Singleton instances are likely to appear in the concurrent environment. Thread safety needs to be realized. There are several methods to ensure the thread safety of lazy Singleton.

Add synchronization to getInstance method

public class Singleton{
	private Singleton(){}
	private static Singleton single = null;
	public static synchronized Singleton getInstance(){
		if(single == null){
			single = new Singleton();
		}
		return single;
	}
}

Locking double judgment, referred to as DCL lazy type for short (there is still a problem under the reflection mechanism)

public class Singleton{
	private Singleton(){}
	//volatile keyword must be added to avoid instruction rearrangement
	private volatile static Singleton single = null;
	if(single == null){
		synchronized(Singleton.class){
			if(single == null){
				single = new Singleton();
				//Allocate memory space
				//Execute the construction method to initialize the object
				//Point this object to this space
			}
		}
	}
	return singleļ¼›
}

Static inner class implementation

public class Holder{
	private Holder(){}
	public static Holder getInstace(){
		return InnerClass.HOLDER;
	}
	public static class InnerClass{
		private static final HOLDER = new HOLDER();
	}
}

2, Hungry Han single case mode

//The starving singleton mode instantiates the object when it is loaded for the first time.
//Hungry Chinese style has created a static object for the system to use at the same time as the class is created, which will not change in the future, so it is inherently thread safe.
public class Hungry{
	private Hungrt(){}
	private static final Hungry hungry = new Hunger();
	//Static factory method
	public static Hungry getInstance(){
		return hungry;
	}
}

3, Enumeration itself is a singleton pattern, which cannot be destroyed by reflection mechanism. Enumeration itself is a class with a constructor and two parameters, String and int

Factory mode

effect:
It realizes the separation of creator and caller
Detailed classification:

  • Simple factory mode
  • Factory method model
  • Abstract factory pattern

Seven principles of OOP

  • Opening and closing principle: a software entity should be open to extensions and closed to modifications.
  • Dependency Inversion Principle: program for the interface, not for the implementation.
  • Dimitri's Law: communicate only with your friends and avoid communicating with strangers.

Core essence

Instantiated objects do not use new, but use factory methods instead
The implementation class will be selected to create objects for unified management and control. This decouples the caller from our implementation class.

Three modes

  1. Simple factory mode: used to produce any product in the same hierarchical structure (for adding new products, the existing code needs to be overwritten)
  2. Factory method mode: used to produce fixed products in the same hierarchical structure (any product can be added)
  3. Abstract factory pattern: create other factories around one super factory. The super factory is also known as the factory of other factories.

Simple factory mode

That is to hand over the instantiation of objects to a factory class. Users do not need to instantiate objects. They can directly call this factory class to obtain instance objects.

For example, now I want to buy a car, and there are many kinds of cars.

//First create a vehicle interface
public Interface Car{
	void name();
}

//Create a BMW inherited interface
public class Bwm implements Car{
	public void name(){
		System.out.println("This is a BMW");
	}
}

//Create a public interface inherited by Wuling Hongguang
public class Wuling implements Car{
	public void name(){
		System.out.pringtln("This is a Wuling Hongguang");
	}
}

//Create a factory class to help us instantiate these two objects, so that when we need to use one or both of these two classes, we only need to call the factory class.
public class CarFactory{
	public static Car getCar(String name){
		if(name.equals("bmw")){
			return new Bwm();
		}else if(name.equals("Wuling Hongguang")){
			return new Wuling();
		}else{
			return null;
		}
	}
}

There is a problem with the simple factory mode. It does not meet the opening and closing principle in OOP, that is, it is not easy to expand. If you modify it, you need to change the source code. At this time, you can use the factory method mode.

Factory method model

Everyone has their own factory, and then implement the interface of the general factory. In this way, when we add the vehicle class and its separate factory class during expansion, we don't need to modify the code on the General Factory, which meets the opening and closing principle.

//First create a vehicle interface
public Interface Car{
	void name();
}

//Create a BMW inherited interface
public class Bwm implements Car{
	public void name(){
		System.out.println("This is a BMW");
	}
}

//Create a common interface inherited by Wuling Hongguang
public class Wuling implements Car{
	public void name(){
		System.out.println("This is a Wuling Hongguang");
	}
}

//Create a factory general interface and define the method of vehicle
public Interface CarFactory{
	Car getCar();
}

//Defines the factory class for Bwm
public class BwmFactory implements CarFactory{
	public Car getCar(){
		return new Bwm();
	}
}

//Defines the factory class for Wuling
public class WulingFactory implements CarFactory{
	public Car getCar(){
		return new Wuling();
	}
}

In this way, when we want to extend other car types, we only need to add its classes and factories. We can directly implement the interface without modifying the original code. For example, we want to add a Benchi car.

//Create a Mercedes Benz inherited interface
public class Benchi implements Car{
	public void name(){
		System.out.println("This is a Mercedes Benz");
	}
}

//Define Benchi's factory class
public class BenchiFacatory implements CarFactory{
	public Car getCar(){
		return new Benchi();
	}
}

Abstract factory pattern

Definition: the abstract factory pattern provides an interface to create a series of related or interdependent objects without specifying their specific classes.

Applicable scenarios:

  • The client (application layer) does not depend on the product class, how the instance is created, implementation and other details.
  • Emphasize that a series of related product objects (belonging to the same product family) are used together, and creating objects requires a lot of repetitive code
  • Provide a library of product classes. All products appear with the same interface, so that the client does not depend on the specific implementation.

advantage:

Code isolation of specific products in the application layer, regardless of the details of creation.
Create a series of products together.

Disadvantages:

All possible product sets are specified, and it is difficult to expand new products in the product cluster
It increases the abstraction and understanding difficulty of the system

  • Simple factory mode (static factory mode): although it does not conform to the design principles to some extent, it is actually used most
  • Factory method mode: extend by adding new factory classes without modifying existing classes
  • Abstract factory mode: products can not be added, but families can be added

Application scenario:

  • getInstance method of Calendar in JDK
  • Acquisition of Connection object in JDBK
  • Creating management bean objects in the IOC container in Spring
  • newInstance method of Class object in reflection

Keywords: Java

Added by thecard on Sun, 21 Nov 2021 13:14:21 +0200