Java design pattern (seven principles and singleton pattern)

Posted by lipun4u on Sun, 20 Feb 2022 13:58:55 +0100

1. Overview of Java design patterns

1.1 purpose and importance of design mode

(1) In software engineering, design pattern is a solution to the common (recurring) problems in software design.

(2) Code reusability, readability, scalability and reliability are the characteristics of high cohesion and low coupling.

1.2 seven principles of design mode

1.2.1 principle of single responsibility

(1) Basic introduction:

a. A class should focus on implementing a function.

(2) Precautions and principles:

a.That is, a class is responsible for only one responsibility.
b.Improve the readability and maintainability of the class
c.Reduce risks caused by changes

1.2.2 interface isolation principle

(1) Basic introduction:

a.The client should not rely on interfaces it does not need, that is, the dependence of one class on another should be established
	On the smallest interface

1.2.3 Dependency Inversion Principle

(1) Basic introduction:

a.High level modules should not rely on low-level modules, and both should rely on their abstraction
b.Abstract should not rely on details, details should rely on abstraction
c.The central idea of dependency inversion is interface oriented programming
d.The purpose of using interfaces or abstract classes is to formulate specifications without involving any specific operations,
	Give the details of the presentation to their implementation class to complete

(2) Dependent delivery method:

a.Interface transfer
b.Construction mode transmission
c.setter Mode transmission

(3) Principles and precautions of Dependence Inversion

a.Low level modules should have abstract classes or interfaces as much as possible, or both, so that the program stability is better
b.The declaration type of variables should be abstract classes or interfaces as much as possible, so that there is no relationship between our variable references and instantiated objects,
There is a buffer, which is conducive to program expansion and optimization
c.Follow the principle of Richter substitution in inheritance

1.2.4 Richter's replacement principle

(1) Let's talk about the thinking and explanation of inheritance first:

a.Inheritance contains such a layer of meaning:The inverse method in the parent class is already implemented, which is actually set
	All the requirements and requirements of the rules and regulations must be complied with
	If subclasses modify these implemented methods arbitrarily, it will destroy the whole inheritance system.
b.When inheritance brings traversal to the program, it also brings disadvantages. For example, using inheritance will
	Bring invasiveness to the program, reduce the portability of the program, and increase the coupling of objects. If
	If a class is inherited by other classes, all subclasses must be considered when the class needs to be modified,
	Moreover, after the modification of Cereals, all involved subclasses may fail.

(2) How to solve the problem of inheritance:

a.The common practice is:The original parent and child classes inherit a more popular base class. Original
	Remove all inheritance relationships and replace them with dependency, aggregation, combination and other relationships.

(3) Basic introduction:

a.All places that reference the base class must be able to use the objects of its subclasses transparently.

b.When using inheritance, follow the Richter substitution principle and try not to override the methods of the parent class in the subclass.

c.The Richter substitution principle tells us that inheritance actually enhances the coupling between the two classes, and when appropriate
	In this case, the problem can be solved through aggregation, combination and dependency.

1.2.5 opening and closing principle (OCP)

(1) Basic introduction:

1)The opening and closing principle is the most basic and important design principle in programming

2)A software entity, such as classes, modules and functions, should be open to expansion and closed to modification,
	Build the framework with abstraction and extend the details with implementation
3)When the software needs to change, try to realize the change by expanding the behavior of the software entity
	Change is not achieved by modifying existing code.
4)Follow other principles in programming, and the purpose of using design patterns is to follow the opening and closing principles

1.2.6 Demeter's law

(1) Basic introduction:

1)One object should have minimal knowledge of other objects

2)The closer the relationship between classes, the greater the degree of coupling

3)It is also called the least known rule, that is, the less a class knows about the class it depends on, the better,
	In other words, as for the complexity of the dependent classes, try to encapsulate the logic in the class
	The Ministry of foreign affairs, in addition to providing public Method, do not disclose any information
4)Only communicate with direct friends

5)Direct friends:Each object will have a coupling relationship with other objects, as long as two
	There is a coupling relationship between objects. We say that the two objects are friends. Coupling
	There are many ways to combine, such as dependency, association, combination, aggregation, etc. Among them, we call
	Now the classes in the member variables, method parameters and method return values are direct friends. and
	The class appearing in the local variable is not a direct friend, that is, a strange class
	It's best not to appear inside a class as a local variable.

(2) Precautions and details of Dimitri's Law:

1)The coupling between classes is Dimitri's law

2)be careful:Since each class reduces unnecessary dependencies, Dimitri's law is just to
	To reduce the coupling relationship between classes does not require no dependencies at all

1.2.7 synthetic multiplexing principle

(1) Basic introduction:

1)The principle is to use synthesis as much as possible/Aggregation, not inheritance.

1.3 design principles and core ideas

(1) Find out what changes may be needed in the application and separate them. Don't mix with code that doesn't need to change.

(2) Programming for interfaces, not for implementations

(3) Strive for loose coupling design between interactive objects

2. Three types of design modes (23 modes)

2.1 creation mode

(1) Create mode:

Singleton pattern abstract factory pattern prototype pattern builder pattern factory pattern.

2.2 structural mode

(1) Structural mode:

Adapter mode bridge mode decoration mode combination mode appearance mode sharing mode agent mode

2.3 behavioral model

(1) Behavioral model:

(3)Template mode command mode visitor mode iterator mode observer mode 
	Intermediary mode memo mode interpreter mode state mode strategy mode responsibility chain mode

3. Secret start of mode

3.1 single case mode (eight in total)

3.1.1 starvation mode (static variable):

(1) Advantages and disadvantages:

a.Advantages: this method is simple, that is, the instantiation is completed when the class is loaded to avoid
	The thread synchronization problem is solved.

b.Disadvantages: the instantiation is completed when the class is loaded, and the lazy loading of
	If you haven't used this instance from beginning to end, it will cause unnecessary waste

c.This method is based on classloder The mechanism avoids the synchronization problem of multithreading, however,
	instance The instance is initialized when the class is loaded. In singleton mode, most
	All calls getInstance method. However, there are many reasons for class loading,
	Therefore, it is not certain that there are other methods that cause class loading. At this time, initialization is required instance
	It didn't reach lazy loading Effect of

d.Conclusion: This singleton mode is available, but it may cause a waste of memory

(2) Code example:

package com.pattern.Design mode.Singleton mode;

public class Static variables of hungry Han formula {
    public static void main(String[] args) {
        // test
        Singleton instance = Singleton.getInstance();
        Singleton instance1 = Singleton.getInstance();
        System.out.println(instance == instance1);  // true
        System.out.println(instance.hashCode() == instance1.hashCode()); // true

class Singleton{
    // 1. The constructor is privatized, and the external cannot be new
    private Singleton(){

    // 2. Create instances within this class
    private final static Singleton singLeton = new Singleton();

    // 3. Provide a public static method to return the instance object
    public static Singleton getInstance(){
        return singLeton;


3.1.2 starvation mode (static code block):

(1) Advantages and disadvantages:

a.This method is actually similar to the above method, except that the process of class instantiation is handed over to the user
	The static code block is given to implement, that is, the static code is executed when the class is loaded
	The code in the code block initializes the instance of the class. The advantages and disadvantages are the same as above

b.Conclusion: This singleton mode is available, but it will also cause a waste of memory

(2) Code example:

package com.pattern.Design mode.Singleton mode;

public class Starving static code block {
    public static void main(String[] args) {
        Singleton01 singleton01 = Singleton01.getInstance();
        Singleton01 s = Singleton01.getInstance();
        System.out.println(s == singleton01);
        System.out.println(s.hashCode() == singleton01.hashCode());

class Singleton01{
    // 1. The constructor is privatized, and the external cannot be new
    private Singleton01(){

    // 2. Create instances within this class
    private static Singleton01 singLeTon;

    static {  // In a static code block, create an object
        singLeTon = new Singleton01();

    // 3. Provide a public static method to return the instance object
    public static Singleton01 getInstance(){
        return singLeTon;


3.1.3 lazy (thread unsafe)

(1) Advantages and disadvantages:

a.It worked lazy loading But it can only be used in single thread

b.If in multithreading, a thread enters if(singleton == null)Sentence judgment,
	Before it is too late to execute, another thread also passes the judgment, which will generate multiple instances,
	Therefore, this method cannot be used under multithreading

c.Conclusion: do not use this method in actual development

(2) Code example:

package com.pattern.Design mode.Singleton mode;

public class Lazy thread safety {
    public static void main(String[] args) {
        Singleton03 singleton03 = Singleton03.getInstance();
        Singleton03 singleton04 = Singleton03.getInstance();
        System.out.println(singleton03 == singleton04);

class Singleton03{

    private static Singleton03 singleton03;

    private Singleton03(){


    // Provide a static common method, add synchronous processing code, and solve the thread safety problem, that is, lazy
    public static synchronized Singleton03 getInstance(){
        if (singleton03 == null){
            singleton03 = new Singleton03();
        return singleton03;


3.1.4 lazy (thread safety, synchronization method)

(1) Advantages and disadvantages:

a.Solves the thread safety problem

b.The efficiency is too low. When each thread wants to obtain an instance of a class, it executes
	getInstance Methods need to be synchronized, but in fact, this method only executes
	One time is enough. If you want to get this instance later, you can do it directly return That's it. How
	The efficiency of synchronization is too low

c.Conclusion: in practice, it is not recommended to use

(2) Code example:

package com.pattern.Design mode.Singleton mode;

public class Lazy threads are unsafe {
    public static void main(String[] args) {
        Singleton02 singleton02 = Singleton02.getInstance();
        Singleton02 singleton021 = Singleton02.getInstance();
        System.out.println(singleton02 == singleton021);

class Singleton02{

    private static Singleton02 singleton02;

    private Singleton02(){


    // Provide a static common method. When using this method, you can create an instance, that is, lazy
    public static Singleton02 getInstance(){
        if (singleton02 == null){
            singleton02 = new Singleton02();
        return singleton02;


3.1.5 lazy (thread safe, synchronous code block)

(1) Advantages and disadvantages:

a.As in the third scenario, suppose a thread enters if(singleton == null)
	If the judgment statement is not executed before another thread passes the judgment, it will be generated
	Multiple instances, so this method cannot be used under multithreading

b.Conclusion: in the actual development, do not use.

(2) Code example:

package com.pattern.Design mode.Singleton mode;

public class Lazy leave_Thread safe and synchronized {
    public static void main(String[] args) {


class Singleton04{

    private static Singleton04 singleton04;

    private Singleton04(){


    // Provide a static common method, lazy
    public static Singleton04 getInstance(){
        if (singleton04 == null){ // But in fact, thread insecurity has been generated here
            // Add synchronous processing code to solve thread safety problems
            synchronized (Singleton04.class){
                singleton04 = new Singleton04();
        return singleton04;


3.1.6 double check

(1) Advantages and disadvantages:

a.Double-check The concept is commonly used in multithreading development, which is to carry out two
	second if(singleton == null)inspect

b.Avoid repeated method synchronization

c.Thread safety: delayed loading, high efficiency

d.Conclusion: it is recommended in practical development

(2) Code example:

package com.pattern.Design mode.Singleton mode;

public class duplication check {
    public static void main(String[] args) {
        Singleton05 singleton05 = Singleton05.getInstance();
        Singleton05 singleton06 = Singleton05.getInstance();
        System.out.println(singleton05 == singleton06);


class Singleton05{
    private static volatile Singleton05 singleton05;

    private Singleton05(){


    // Provide a static method, add double check code to solve thread safety problems and lazy loading problems at the same time
    public static synchronized Singleton05 getInstance(){
        if (singleton05 == null){
            synchronized (Singleton05.class){
                if (singleton05 == null){
                    singleton05 = new Singleton05();
        return singleton05;

3.1.7 static internal class

(1) Advantages and disadvantages:

a.This method adopts the mechanism of class loading to ensure that there is only one thread for initialization

b.Static inner class mode Singleton06 The class is not instantiated immediately when it is loaded,
	Instead, when instantiation is needed, call getInstance Method before loading
	SingletonInstance Class to complete Singleton06 instantiation 

c.The static properties of a class will only be initialized when the class is first loaded, so here we are
	Used JVM Thread safety is guaranteed. When the class is initialized, other lines
	Cheng can't get in

d.Advantages: thread insecurity is avoided, delayed loading is realized by using the characteristics of static internal classes, and the efficiency is high

e.Conclusion: it is recommended to use

(2) Code example:

package com.pattern.Design mode.Singleton mode;

public class Static inner class {
    public static void main(String[] args) {
        Singleton06 singleton06 = Singleton06.getInstance();
        Singleton06 singleton07 = Singleton06.getInstance();
        System.out.println(singleton06 == singleton07);

class Singleton06{
    private Singleton06(){


    // The static inner class provides a static attribute Singleton06
    private static class SingletonInstance{
        private static final Singleton06 SINGLETON_06 = new Singleton06();


    // Provide a static method to directly return singletoninstance SINGLETON_ 06
    public static  synchronized Singleton06 getInstance(){

        return SingletonInstance.SINGLETON_06;

3.1.8 enumeration

(1) Advantages and disadvantages:

a.borrow jdk1.5 The enumeration added in to realize the singleton mode can not only avoid multi-threaded synchronization
	It also prevents deserialization from re creating new objects.

b.Conclusion: it is recommended to use

(2) Code example:

package com.pattern.Design mode.Singleton mode;

public class enumeration {
    public static void main(String[] args) {
        Singleton07 singleton07 = Singleton07.INSTANCE;
        Singleton07 singleton08 = Singleton07.INSTANCE;
        System.out.println(singleton07 == singleton08);



enum Singleton07{
    public void shallow(){



Topics: Java Design Pattern