zoukankan      html  css  js  c++  java
  • 设计模式(一)__单例设计模式

    先来介绍一下什么是设计模式,设计模式起先是从建筑行业借鉴来的,然后慢慢发展到了今天这个样子。

    设计模式是解决问题最行之有效的思想,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。

    java有23种设计模式,今天就先来介绍一种:单例设计模式

    单例设计模式:

      有时候当你需要保证一个类在内存中的对象唯一性的时候,比如多程序读取一个配置文件时,建议配置文件封装成对象。会方便操作其中数据,又要保证多个程序读到的是同一个配置文件对象,就需要该配置文件对象在内存中是唯一的。那么这时候你就需要用到单例设计模式了。

      那么,如何保证对象的唯一性呢?

        思想:

      1. 不让其他类创建该类对象。
      2. 在本类中创建一个本类对象
      3. 对外提供方法,让其他程序获取这个对象

        步骤:

          1. 因为创建对象都需要构造函数初始化,所以只需要将本类中的构造函数私有化,这样其他类就不能创建该类对象了。

          2. 在本类中创建一个本类对象

          3. 定义一个公有方法,返回该对象,让其他类访问。(作用:可控) 

    好了,上面就把单例模式的思路给大家说了下,单例模式的写法有好几种,这里主要介绍两种:懒汉式单例、饿汉式单例。

    一:饿汉式

    class Single {
        private Single() {} // 私有化构造函数。
    
        private static final Single s = new Single(); // 创建私有并静态的本类对象。
    
        public static Single getInstance() { // 定义公有并静态的方法,返回该对象。
            return s;
        }
    }

    饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

    二:懒汉式

    class Single {
        private Single() {}
    
        private static Single s = null;
    
        public static Single getInstance() {
            if (s == null)
                s = new Single();
            return s;
        }
    }

    但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Single实例,要实现线程安全,可通过多判断加同步来解决。

    class Single {
        private Single() {};
    
        private static Single s = null;
    
        public static Single getInstance() {
            if (s == null) {
                synchronized (Single.class) {
                    if (s == null) {
                        s = new Single();
                    }
                }
            }
            return s;
        }
    }

    --------------------------------------------------------------------------------------------

    双重锁检查只能在jdk1.5以后才能有效,1.5以前在java对象模型中的无序写问题不能保证。

    查阅了一下资料,发现还可以通过静态内部类来解决延迟加载的安全问题。

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

    这种方式既实现了线程安全,又避免了同步带来的性能影响

    那么为什么这样可以实现单例呢?

    先来介绍一下内部类:

    内部类分为对象级别和类级别,类级内部类指的是,有static修饰的成员变量的内部类。如果没有static修饰的成员变量的内部类被称为对象级内部类。

    类级内部类相当于其外部类的static成员,它的对象与外部类对象间不存在依赖关系,相互独立,因此可直接创建。而对象级内部类的实例,是必须绑定在外部对象实例上的。类级内部类只有在第一次被使用的时候才被会装载。

    当getInstance方法第一次被调用的时候,它第一次读取Holder.instance,内部类Holder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静态域,从而创建Single的实例,由于是静态的域,因此只会在虚拟机装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。

    这个模式的优势在于,getInstance方法并没有被同步,并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本。

    个人推荐此种方式。

    --------------------------------------------------------------------------------------------

    三:饿汉式和懒汉式区别

    饿汉比较急,类一旦加载,就把单例初始化完成。

    懒汉太懒了,只有当调用getInstance的时候,才会去初始化这个单例。

    饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题。

    懒汉式本身是非线程安全的。

    饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。

    而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,而且因为线程安全问题,需要加同步,效率上比较低。

    总之,从速度和反应时间角度来讲,饿汉式好;从资源利用效率上说,延迟加载(又称懒汉式)好。

  • 相关阅读:
    JS和C#对Json的操作
    JS图形化插件利器组件系列 —— Gojs组件
    Android APK反编译 apktool使用教程
    UML系列图
    多线程学习 ---- 系列教程
    大型网站架构之系列
    经典算法题锦集
    基本算法系列15天速成
    居转户--相关信息
    使用C#创建Windows服务
  • 原文地址:https://www.cnblogs.com/makaruila/p/4831342.html
Copyright © 2011-2022 走看看