zoukankan      html  css  js  c++  java
  • 设计模式学习(三):确保对象的唯一性—单例模式

    一、简介

          单例模式是用于创建那些在软件系统中独一无二的对象。

    二、单例模式的意图

          在实际开发过程中经常遇见这样的情况,为了节约系统资源,有时需要确保系统中某个类只有唯一一个实例,当这个唯一实例创建成功之后,无法再创建一个同类型的其他对象,所有的操作都只能基于这个唯一实例。例如,Windows任务管理器在系统中有且仅有一个。

    三、单例模式概述

    (1)概念

    单例模式:确保某一类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类成为单例类,它提供全局访问的方法。

    (2)类图

    (3)核心代码

     1 public class Singleton
     2 {
     3     //私有构造函数
     4     private Singleton(){}
     5     
     6     //静态变量
     7     private static Singleton instance = null;  
     8    
     9     //公有的静态方法返回该实例
    10     public static Singleton GetInstance()
    11     {
    12           if(instance == null)
    13           {
    14                   instance = new Singleton();
    15           }
    16           return instance;
    17     }   
    18 }

    说明:

    ①为了确保Singleton实例的唯一性,需要禁止类的外部直接使用new来创建对象,因此需要将Singleton的构造函数的可见性改为private。

    ②为了让外界可以访问这个唯一实例,需要在Singleton中定义一个静态的Singleton类型的私有变量。

    ③为了让外界可以访问这个唯一实例,需要增加一个公有的静态方法来返回这个唯一实例。

    (4)单例模式三要点

    ①某个类只能有一个实例(通过私有构造函数实现)。

    ②它必须自行创建这个实例。

    ③它必须自行向整个系统提供这个实例(通过公有的静态方法来实现)。

    四、饿汉式单例与懒汉式单例

    <1>饿汉式单例

     当类被加载时,静态变量instance会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建。

     ①类图

    ②代码

     1 public class EagerSingleton
     2 {
     3     private static EagerSingleton instance = new EagerSingleton();
     4      
     5     private EagerSingleton(){}
     6     
     7     public static EagerSingleton GetInstance()
     8     {
     9           return instance;
    10     }  
    11 }

    <2>懒汉式单例

    懒汉式单例在第一次调用GetInstance()方法时实例化,在类加载时并不自行实例化,这种技术又称为延迟加载技术,即需要的时候再加载实例。

    ①类图

    ②代码

     1 public class LazySingleton
     2 {
     3       private static LazySingleton instance = null;
     4 
     5       private LazySingleton(){}
     6 
     7       public static LazySingleton GetInstance()
     8       {
     9              if(instance == null)
    10              {
    11                    instance = new LazySingleton();
    12              }
    13              
    14              return instance;
    15       }
    16 }

    <3>两种模式的比较

          饿汉式单例类在类加载时就将自己实例化,它的优点在于无须考虑多线程访问问题,可以确保实例的唯一性;从调用速度和反应时间角度来讲,由于单例对象一开始就被创建,因此要优于懒汉式单例。但是无论系统在运行时是否需要使用该单例对象,由于在类加载时该对象就需要创建,因此从资源利用效率角度来讲,饿汉单例不及懒汉单例,而且在系统加载时由于需要创建懒汉式单例对象,加载时间可能会比较长。

         懒汉式单例类在第一次使用时创建,无须一直占用系统资源,实现了延迟加载,但是必须处理好多线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的几率比较大,需要通过双重检查锁定机制进行控制,这将导致系统性能受到一定影响。

    五、单例模式总结

    1.主要优点

    (1)单例模式提供了对唯一实例的受控访问。

    (2)由于系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销毁的对象,单例模式无疑可以提高系统的性能。

    (3)允许可变数目的实例。基于单例模式,开发人员可以自行扩展,使用与控制单例对象相似的方法来制定个数的实例对象,既节省系统资源,又解决了单例模式对象共享过多有损性能的问题。

    2.主要缺点

    (1)由于单例模式中没有抽象层,因此单例类的扩展有很大困难。

    (2)单例类的职责过重,在一定程度上违背了单一职业原则。因为既提供了业务方法,有提供了创建对象的方法,将对象的创建和对象本身的功能耦合在了一起。

    (3)很多面向对象预言的运行环境都提供了自动垃圾回收技术,因此,如果实例化的共享对象长时间不利用,系统会认为它是垃圾,会自动销毁并回收资源,下次利用时又将重新实例化,这将导致共享的单例对象状态的丢失。

    3.使用场景

    (1)系统只需要一个实例对象。例如系统要求提供一个唯一的序列号生成器或资源管理器,或者需要考虑资源消耗太大而只允许创建一个对象。

    (2)客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

  • 相关阅读:
    云原生时代,应用架构将如何演进?
    OpenKruise:解放 DaemonSet 运维之路
    端应用研发进入云原生时代
    如何通过 Serverless 技术降低微服务应用资源成本?
    让容器应用管理更快更安全,Dragonfly 发布 Nydus 容器镜像加速服务
    一文教会你如何写复杂业务代码
    gitalk未找到相关的 Issues 进行评论解决方案
    dpkg error processing package XXX (--configure) 解决方法 (ubuntu右上角红色警告)
    Linux添加快捷方式
    linux开机部署
  • 原文地址:https://www.cnblogs.com/sunshineground/p/3585882.html
Copyright © 2011-2022 走看看