当前位置:网站首页>Common setting modes

Common setting modes

2022-06-21 17:33:00 Timely

Catalog

1. Why you need to learn design patterns

Two 、 Common setting modes

2.1 The singleton pattern

2.1.1 Concept

2.1.2 Use scenarios

2.1.3 Advantages and disadvantages

2.1.4 Example

2.2 Factory mode

2.2.1 Concept

2.2.2 Use scenarios

2.2.3 Factory method


1. Why you need to learn design patterns

Design patterns (Design pattern) Represents best practice , It is the experience summary of many excellent software developers , A solution to a particular problem . It is not a grammatical rule , Nor is it tied to a particular language . The reusability of code can be improved by using design patterns properly , Maintainability , Extensibility , Robustness and security , These are very important non functional requirements of the system .

The widespread use of design patterns began with 1995 year ,GOF( Gang of four ) Published 《 Design patterns : Reusable object-oriented software foundation 》.

The sample code related to this section :

https://gitee.com/lisenaq/patterndemo.git

Two 、 Common setting modes

2.1 The singleton pattern

2.1.1 Concept

Ensure that only one instance is in memory

2.1.2 Use scenarios

such as : Management of system configuration files , These configuration files can be read and written using a singleton object , When configuration information is needed elsewhere in the system , Just use the singleton object to get it , This facilitates unified management of configuration information .

2.1.3 Advantages and disadvantages

* advantage :

  • There is only one object in memory , Save memory space ;
  • Avoid frequent creation of destroyed objects , Can improve performance ;
  • Avoid multiple use of shared resources , Simplify access ;
  • Provide a global access point for the whole system .


* shortcoming :

  • Not for objects that change frequently ;
  • Abuse of single case will bring some negative problems , For example, in order to save resources, the database connection pool object is designed as a single instance class , May cause too many programs sharing connection pool objects to overflow connection pool ;

2.1.4 Example

1. Hunger mode : Instantiate objects directly

package org.lisen.patterndemo.singleton;

/**
 *  The singleton pattern , Hunger is loaded 
 */
public class SingletonDemo01 {

    //1.  You need to have a private constructor , Prevent this class from passing new To create an instance 
    private SingletonDemo01(){}

    //2.  Hunger mode , First, generate an instance 
    private static final SingletonDemo01 instance = new SingletonDemo01();

    //3.  Static methods , Used to get the generated instance 
    public static SingletonDemo01 getInstance() {
        return instance;
    }

    public String hello(String name) {
        return "hello " + name;
    }

    /*
     *  Test whether the multi-threaded singleton mode is safe 
     * @param args
     */
    public static void main(String[] args) {
        /*for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(SingletonDemo01.getInstance().hashCode());
            }).start();
        }*/
        SingletonDemo01 s = SingletonDemo01.getInstance();
        String hello_world = s.hello("hello world");
        System.out.println(hello_world);
    }

}

This straight line method is simple , And it's thread safe .

2. The sluggard model : Instantiate the object when calling the method .

  • The first way to write it :
/**
 *  The singleton pattern :  Slacker type 
 */
public class SingletonDemo02 {

    private SingletonDemo02(){

      // The running time of the simulation constructor 
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }    

    private static SingletonDemo02 singletonDemo02 = null;

    public static SingletonDemo02 getInstance() {

        if (singletonDemo02 == null) {
            singletonDemo02 = new SingletonDemo02();
        }

        return singletonDemo02;
    }

    public String hello(String name) {
        return "hello " + name;
    }

}

Be careful : This method will have problems in multi-threaded access .

  • The second way :

A synchronization lock is added to the previous method synchronized

package org.lisen.patterndemo.singleton;

/**
 *  The singleton pattern :  Slacker type ,  There are threading problems 
 */
public class SingletonDemo03 {

    private SingletonDemo03(){
        // The running time of the simulation constructor 
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static SingletonDemo03 singletonDemo02 = null;

    public static synchronized SingletonDemo03 getInstance() {

        if (singletonDemo03 == null) {

            singletonDemo03 = new SingletonDemo03();
        }

        return singletonDemo03;
    }

    public String hello(String name) {
        return "hello " + name;
    }

    /*
     *  Test whether the multi-threaded singleton mode is safe 
     * @param args
     */
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(SingletonDemo03.getInstance().hashCode());
            }).start();
        }
    }

}
  • The third way
public class SingletonDemo04 {

    private SingletonDemo04() {
    }

    private static SingletonDemo04 singletonDemo04 = null;

    public static  SingletonDemo04 getInstance(){
        // The system reduces the synchronization block to improve performance , Is that OK ?
        if(singletonDemo04 == null) {
            synchronized (SingletonDemo04.class) {
                singletonDemo04 = new SingletonDemo04();
            }
        }
        return singletonDemo04;
    }

    public String hello(String name) {
        return "hello " + name;
    }

}

This method still has thread safety problems

  • The fourth way of writing

Double check based on the previous method   First, judge whether it is empty If it is empty, a synchronization lock will be added     After that Second judgment

package org.lisen.patterndemo.singleton;

/**
 *  The singleton pattern :  Slacker type , Thread safety , But the performance is lower 
 */
public class SingletonDemo05 {

    private SingletonDemo05() {
        // The running time of the simulation constructor 
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static SingletonDemo05 singletonDemo05 = null;

    public static  SingletonDemo05 getInstance(){
        // The system reduces the synchronization block to improve performance , Is that OK ?
        if(singletonDemo05 == null) {
            ///....
            synchronized (SingletonDemo05.class) {
                if(singletonDemo05 == null) {
                    singletonDemo05 = new SingletonDemo05();
                }
            }
        }
        return singletonDemo05;
    }

    public String hello(String name) {
        return "hello " + name;
    }


    /*
     *  Test whether the multi-threaded singleton mode is safe 
     * @param args
     */
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(SingletonDemo05.getInstance().hashCode());
            }).start();
        }
    }

}
  • The fifth way of writing

Write a static inner class Declare a static instance in a static inner class ( Is a single thread without thread safety issues )

package org.lisen.patterndemo.singleton;

/**
 *  The singleton pattern :  Lazy loading ,  Thread safety 
 */
public class SingletonDemo04 {

    // Prevent external instantiation 
    private SingletonDemo04() {
        // The simulation constructor takes time to run 
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    static {

    }

    // Use a static inner class to use a SingletonDemo04 object 
    private static class SingletonDemoHolder {
        private final static SingletonDemo04 instance = new SingletonDemo04();
    }

    public static SingletonDemo04 getInstance() {
        return SingletonDemoHolder.instance;
    }

    public String hello(String name) {
        return "hello " + name;
    }


    /*
     *  Test whether the multi-threaded singleton mode is safe 
     * @param args
     */
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()->{
                System.out.println(SingletonDemo04.getInstance().hashCode());
            }).start();
        }
    }
}
  • The sixth way of writing

 enum enum ( There is no constructor ) It can guarantee the singleton , And thread safety

package org.lisen.patterndemo.singleton;

public enum  SingletonDemo05 {

    INSTANCE;

    public String hello(String name) {
        return "hello " + name;
    }

    /*
     *  Test whether the multi-threaded singleton mode is safe 
     * @param args
     */
    public static void main(String[] args) {

        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                System.out.println(SingletonDemo05.INSTANCE.hashCode());
            }).start();
        }
    }
}

Be careful : Singleton mode should ensure both lazy loading and thread safety

2.2 Factory mode

2.2.1 Concept

Methods or classes used to generate objects , Call it a factory . The singleton pattern mentioned above can also be regarded as a special factory .

2.2.2 Use scenarios

Why working mode is needed , The original use new The way is also very simple , And easy to understand ?

The reason for using the factory is that we can use the factory mode , To centrally control the creation process of objects , This can bring more flexibility to the design . such as :spring Of IOC A container is a classic implementation of the factory pattern .

2.2.3 Factory method

Used to produce the specified series of objects . Take the duck as an example , Ducks have real ducks , Rubber duck , Electronic toy duck, etc . How to easily create a variety of ducks , And control the creation process , To facilitate future maintenance and expansion ?

Class diagram :

  Abstract duck parent class Duck

public abstract class Duck {
 
    abstract public void quack();
 
}

RubberDuck The duck subclass , Inherit Duck Abstract parent class

public class RubberDuck extends Duck {
 
    @Override
    public void quack() {
        System.out.println(" I'm a rubber duck ,");
    }
 
}

 WildDuck The duck subclass , Inherit Duck Abstract parent class

public class WildDuck extends Duck {
 
    @Override
    public void quack() {
        System.out.println(" I am a real duck ");
    }
 
}

 DonaldDuck The duck subclass , Inherit Duck Abstract parent class

public class DonaldDuck extends Duck {
 
    @Override
    public void quack() {
        System.out.println(" I'm Donald Duck ");
    }
 
}

  Write a factory that controls the creation of duck classes DuckFactory 

public class DuckFactory {
 
    // Privatized construction method 
    private DuckFactory(){}
 
    //static  The hungry man pattern instantiates an object of type duck factory class 
    private static DuckFactory duckFactory = new DuckFactory();
    
    // A duck class that defines several subclasses of the graph , Types are distinguished by numbers , It can be added manually 
    public static final int WILD_DUCK = 1;
 
    public static final int RUBBER_DUCK = 2;
 
    public static final int DONALD_DUCK = 3;
 
    public static final int PJ_DUCK = 4;
    
    // The method of getting duck instances according to duck types 
    public static Duck getInstance(int duckType) {
        switch (duckType) {
            case WILD_DUCK:
                // Return directly instantiated duck subclass 
                return new WildDuck();
            case RUBBER_DUCK:
                return new RubberDuck();
            case DONALD_DUCK:
                return new DonaldDuck();
            case PJ_DUCK:
                return new PJDuck();
            default:
                return null;
        }
    }
 
}

test

public class Main {
 
    public static void main(String[] args) {
 
        //DuckFactory Can produce duck objects 
        Duck donaldDuck = DuckFactory.getInstance(DuckFactory.DONALD_DUCK);
        donaldDuck.quack();
 
        Duck wildDuck = DuckFactory.getInstance(DuckFactory.WILD_DUCK);
        wildDuck.quack();
 
        Duck pjDuck = DuckFactory.getInstance(DuckFactory.PJ_DUCK);
        pjDuck.quack();
    }
 
}

The above is about common setting modes 01 The content of

原网站

版权声明
本文为[Timely]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/172/202206211515404395.html