单例设计模式

1.单例模式 是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

一、单例模式的结构

单例模式的主要有以下角色

  • 单例类。只能创建一个实例的类
  • 访问类。使用单例类

二、单例模式的实现

单例设计模式分类两种:

饿汉式:类加载就会导致该单实例对象被创建

懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建

1.饿汉式-方式1 (静态变量方式)

package com.jmj.pattern.singleton.demo02;

/**
 * 饿汉式 :静态代码块
 */
public class Singleton {


    private Singleton(){

    }

    //声明Singleton类型的变量
    private static Singleton singleton ;

    //在静态代码块中进行复制
    static {
        singleton=new Singleton();
    }

    public static Singleton getInstance(){
        return singleton;
    }



}
package com.jmj.pattern.singleton.demo01;

/**
 * 饿汉式 :静态成员 变量
 */
public class Singleton {

    //1.私有构造方法
    private Singleton(){};

    //2.在本类中创建本类对象
    private static Singleton singleton =new Singleton();

    //3.提供一个公共的访问方式,让那个外界获取该对象
    public static Singleton getInstance(){
        return singleton;
    }

}

2、懒汉式

线程安全

package com.jmj.pattern.singleton.demo03;

/**
 * 懒汉式 线程不安全
 */
public class Singleton {
    private Singleton(){}

    private static Singleton singleton;


    //对外提供访问方式

    public static synchronized Singleton getInstance(){
       if (singleton==null){
           singleton=new Singleton();
           return singleton;
       }

        return singleton;
    }





}

双重检查锁

package com.jmj.pattern.singleton.demo04;

/**
 * 懒汉式 双重检查锁方式
 */
public class Singleton {
    private Singleton(){}

    private static volatile Singleton singleton;


    //对外提供访问方式

    public static Singleton getInstance(){
      //第一次判断,如果instance的值不为null ,不需要抢占锁,直接返回对象
        if(singleton==null){
            synchronized (Singleton.class){
                if (singleton==null){
                    singleton=new Singleton();
                }
            }


      }
      return singleton;
    }





}

静态内部类方式 

单例设计模式_第1张图片单例设计模式_第2张图片

枚举

单例设计模式_第3张图片 序列化反序列化破坏单例模式

package com.jmj.pattern.singleton.demo07;


import java.io.*;

/**
 * 测试使用反射破坏单例模式
 */

public class Client {
    public static void main(String[] args) throws Exception {
//        writeObject2File();
        readObject2File();
        readObject2File();
    }

    //从文件读取数据(对象)
    public static void readObject2File() throws Exception {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("src/main/resources/static/a.txt"));
        Singleton singleton = (Singleton) objectInputStream.readObject();
        System.out.println(singleton);
        //释放资源
        objectInputStream.close();

    }
    //向文件中写数据 (对象)
  public static void writeObject2File() throws Exception {
      Singleton instance = Singleton.getInstance();

      ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("src/main/resources/static/a.txt"));
        objectOutputStream.writeObject(instance);
        objectOutputStream.close();
  }


}
package com.jmj.pattern.singleton.demo07;

import java.io.Serializable;

/**
 * 懒汉式 匿名内部类
 */
public class Singleton implements Serializable {
    private Singleton(){}


    /**
     * 静态内部类,只会被 在调用里面属性或者  方法的时候,才会被类加载
     * 类加载的时候才加载  ,final 修饰 不会被修改
     */
    private static class SingletonHolder{
        private static   Singleton singleton =new Singleton();
    }


    //对外提供访问方式
    public static Singleton getInstance(){
     return SingletonHolder.singleton;
    }





}

单例设计模式_第4张图片

反射破坏单例模式

package com.jmj.pattern.singleton.demo08;

import java.io.Serializable;

/**
 * 懒汉式 匿名内部类
 */
public class Singleton {
    private Singleton(){}


    /**
     * 静态内部类,只会被 在调用里面属性或者  方法的时候,才会被类加载
     * 类加载的时候才加载  ,final 修饰 不会被修改
     */
    private static class SingletonHolder{
        private static   Singleton singleton =new Singleton();
    }


    //对外提供访问方式
    public static Singleton getInstance(){
     return SingletonHolder.singleton;
    }





}
package com.jmj.pattern.singleton.demo08;


import java.lang.reflect.Constructor;

/**
 * 测试使用反射破坏单例模式
 */

public class Client {
    public static void main(String[] args) throws Exception {

        //1.获取Singleton的字节码对象
        Class singletonClass = Singleton.class;
        Constructor declaredConstructor = singletonClass.getDeclaredConstructor(null);
        declaredConstructor.setAccessible(true);
        Singleton singleton = declaredConstructor.newInstance(null);
        Singleton singleton1 = declaredConstructor.newInstance(null);
        Singleton singleton2 = declaredConstructor.newInstance(null);
        System.out.println(singleton);
        System.out.println(singleton1);
        System.out.println(singleton2);
    }



}

序列化反序列化破坏单例模式解决方案

package com.jmj.pattern.singleton.demo07;

import java.io.Serializable;

/**
 * 懒汉式 匿名内部类
 */
public class Singleton implements Serializable {
    private Singleton(){}


    /**
     * 静态内部类,只会被 在调用里面属性或者  方法的时候,才会被类加载
     * 类加载的时候才加载  ,final 修饰 不会被修改
     */
    private static class SingletonHolder{
        private static   Singleton singleton =new Singleton();
    }


    //对外提供访问方式
    public static Singleton getInstance(){
     return SingletonHolder.singleton;
    }



    public Object readResolve(){
        return SingletonHolder.singleton;
    }


}

反射破解单例模式解决方案:

首先加个静态变量做标志位,然后 在构造里加锁,锁字节码对象,构造方法就被 加了同步锁了

Runtime 源码就是饿汉式单例模式

package com.jmj.pattern.singleton.demo09;

import java.io.IOException;
import java.io.InputStream;

public class RuntimeDemo {
    public static void main(String[] args) throws IOException {
        Runtime runtime = Runtime.getRuntime();

        long l = runtime.freeMemory();
        System.out.println(l);
        //要的是一个命令
        Process exec = runtime.exec("ipconfig");
        //调用process对象
        InputStream inputStream = exec.getInputStream();
        byte[] bytes = new byte[1024 * 1024 * 1024];


        int len = inputStream.read(bytes);
        String s = new String(bytes,0,len,"GBK");
        System.out.println(s);

    }
}

它的作用可以使用Java操作操作系统

你可能感兴趣的:(设计模式,设计模式)