zoukankan      html  css  js  c++  java
  • 单例模式

     

    单例模式

    定义:某个类仅有一个唯一的实例,并且提供一个全局的访问点来访问这一实例。

    注意

      1.该类只能有一个实例

      2.必须是自己创建的这一个唯一的实例

      3.必须自己向整个系统提供这个实例

    代码实现

      1.目的是一个类只有一个实例,并且提供全局的访问点

      2.包含的角色只有一个

      3.构造函数是私有的,无法通过new对象的方式创建实例

      4.有一个静态的私有成员变量和静态的共有的工厂方法

    注意

      1.单例类构造器的可见行为private

      2.提供一个类型为自身的静态私有成员变量

      3.提供共有的静态工厂方法

    优点:

      1.严格控制客户程序访问其唯一的实例。

      2.单例类可以自带一些子类,它的每个子类都是单例类。

      3.该模式的类可以比较容易允许创建一定数目的对象类。

    缺点

      1.单例模式,没有抽象层,扩展比较困难

      2.在一定程度上违背了单一职责原则

      3.容易导致单例状态丢失,系统存在垃圾回收机制,长时间不使用,会被系统自动回收,再次使用就需要再次实例

     、

    实现:

    1.创建一个Singleton类

    public class Singleton {
        //私有构造器
        private  Singleton(){}
    
        //私有的Singleton对象
        private static  Singleton instance = new Singleton();
    
        public static Singleton getInstance(){
            return instance;
        }
    
        public void  Say(){
            System.out.println("Hello Singleton");
        }
    }

     2.创建TestSingleton类:

    在类里使用new 的方法是会报错的

    public class TestSingleton {
        public static void main(String[] args) {
    
            Singleton singleton = Singleton.getInstance();
    
            singleton.Say();
        }
    }

    3.运行结果是

    Hello Singleton

     单例模式的其他实现方式:

    1.懒汉式,线程不安全

    是否 Lazy 初始化:

    是否多线程安全:

    实现难度:

    描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
    这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

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

    2.懒汉式,线程安全

    是否 Lazy 初始化:

    是否多线程安全:

    实现难度:

    描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
    优点:第一次调用才初始化,避免内存浪费。
    缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
    getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。

    public class Singleton {
        //懒汉式
        private static  Singleton instance;
    
        private Singleton(){};
    
        public static synchronized   Singleton getInstance(){
            if (instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }

    3.饿汉式

    是否 Lazy 初始化:

    是否多线程安全:

    实现难度:

    描述:这种方式比较常用,但容易产生垃圾对象。
    优点:没有加锁,执行效率会提高。
    缺点:类加载时就初始化,浪费内存。
    它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。

    public class Singleton {
        
        private  Singleton(){}
    
        private static  Singleton instance = new Singleton();
    
        public static Singleton getInstance(){
            return instance;
        }
    }

    4.双检锁/双重校验锁

    JDK 版本:JDK1.5 起

    是否 Lazy 初始化:

    是否多线程安全:

    实现难度:较复杂

    描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
    getInstance() 的性能对应用程序很关键。

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

    5.登记式/静态内部类

    是否 Lazy 初始化:

    是否多线程安全:

    实现难度:一般

    描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。

    public class Singleton {
        
        private static class Singletontest{
            private static  final Singleton INSTANCE = new Singleton();
        }
        
        private Singleton(){};
        
        public  static  final  Singleton getInstance(){
            return Singletontest.INSTANCE;
        }
        
    }

    备注:

    代码部分的实现以及部分讲解来源于:http://www.runoob.com/design-pattern/singleton-pattern.html

  • 相关阅读:
    Java8 中的 Optional
    阿里云查看本服务器 公网ip地址 命令
    Linux添加alias简化命令
    kafka consumer 配置详解
    Kafka查看topic、consumer group状态命令
    ConcurrentHashMap源码分析
    HashMap源码分析
    Java使用Aspose组件进行多文档间的转换操作
    个人Vim配置(即vim目录下vimrc_)
    暑假个人小结
  • 原文地址:https://www.cnblogs.com/Mrchengs/p/9801530.html
Copyright © 2011-2022 走看看