zoukankan      html  css  js  c++  java
  • 设计模式学习笔记(一)——单例模式

    一、概述

      单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。

       通常我们可以让一个全局变量使得一个对象被访问,但它不能防止实例化多个对象。一个最好的办法就是,让类自身负责保持它的唯一实例。这个类可以保证没有其它实例可以被创建,并且它可以提供一个访问该实例的方法。

       在应用这种模式时,单例对象的类必须保证只有一个实例存在。

    二、实现单例模式

      2.1、单例模式

      单例模式的实现中主要有两种方式:一种是调用方法的时候进行实例化的工作,这种方式称为懒汉式;而另种方式是在类的加载的时候就创建一个实例,这种方式称为饿汉式。

      实现单例模式的思路:定义私有对象的引用(永远是同一个)和一个获取该实例的方法(必须是静态方法,通常使用getInstance 这个方法名);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其它处的代码就无法通过调用该类的构造函数来实例化该类的实体对象,只有通过该类提供的静态方法来获取该类的唯一实例。

      2.2、懒汉模式

      在懒汉式实现的单例模式中,创建对象实例的代码中有个一个判断是否为null的情况,如果在多线程情况下,如果线程A进入这个方法体时,发现对线为null,那么会创建这个类的一个实例,而另一个线程B也紧跟线程A进入这个方法体中,线程V检查对象是否为null的时候,也得出对象为null,那么线程B也会创建一个类型的实例,这样会导致这个类在懒汉式的实现中会出现多个实例的问题。不过在方法体中加上同步锁即可解决该线程安全问题。

    public class Demo1 {
        
        private static Demo1 obj = null;
        
        private Demo1() {
            
        }
        
        // 加上同步(synchronized), 解决线程安全问题
        public synchronized static Demo1 getInstance() {
            if (obj == null) {
                obj = new Demo1();
            }
            return obj;
        }
        
    }

      优点:避免了没有用到对象的情况下创建实例,资源利用率高,不执行getInstance方法就不会被实例。

      缺点:在多线程同时访问的情况下就可能同时创建多个实例,而者多个实例不是同一个对象,虽然后面创建的实例会覆盖先前创建的实例,但还是会存在拿到不同对象的情况。解决这一问题就是加锁synchronized;第一次加载时速度会有延迟,多线程使用不必要的同步开销大。

        

      2.3、饿汉模式

      饿汉式通过在类级别定义一个全局的静态变量,并且立即实例化本类的一个对象并赋值给这个变量,而在返回本类的静态方法中只需要返回这个全局变量即可,无需判断变量是否为null。

    public class Demo2 {
    
        // 静态实例化变量对象
        private static Demo2 obj = new Demo2();
        
        private Demo2() {
            
        }
        
        public static Demo2 getInstance() {
            return obj;
        }
    }

      优点:线程安全;在类加载的同时已经创建好一个静态对象,调用反应速度快。

      缺点:资源效率不高,可能getInstance方法永远不会被执行,但执行该类的其它静态方法或者加载了该类,那么这个实例仍然初始化。

    三、总结

      饿汉式和懒汉式的区别:

      1、线程安全:

        饿汉式是线程安全的,可以直接用于多线程而不会出现问题,懒汉式就不行,它是线程不安全的,如果用于多线程可能会被实例化多次,失去单例作用,如果要把懒汉式用于多线程,有两种方式保证安全性,一种是在getInstance方法上加上同步,另一种是在使用该单例方法前后加锁。

      2、资源加载:

        饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,会占据一定的内存,相应的在调用速度也会更快;而懒汉式故名思意,会延迟加载,在第一次使用该单例的时候才会实例化对象处来,第一次调用时要初始化,如果做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

      适用范围:

        非常耗资源的对象创建(比如读取大文件)

        资源的创建比较昂贵(比数据库的连接)

          只能存在一个对象的时候

      

  • 相关阅读:
    X lvm管理:扩展lv、删除pv、lv,删除物理卷PV
    X 如何在Linux中缩小LVM大小(逻辑卷调整)如何在Linux中缩小LVM大小(逻辑卷调整)
    元素和为目标值的子矩阵数量
    完美矩形问题
    桶排序算法
    组合数组合
    求两个有序数组的第k大的数(默认两有序数组都为从小到大)
    二叉树的遍历
    卡特兰数
    二叉排序树
  • 原文地址:https://www.cnblogs.com/hejianliang/p/9099351.html
Copyright © 2011-2022 走看看