【设计模式】——创建类型模式——单例模式

本文详细介绍了Java中的单例模式,包括其动机、定义和结构。讨论了饿汉式和懒汉式的实现,以及它们在多线程环境下的问题与解决方案。最后,提出了静态内部类作为实现单例的最优方法,它具有延迟加载和线程安全的特点。
摘要由CSDN通过智能技术生成

单例模式

设备控制,一次只存在一个实例

动机

在正常情况下,一个计算机只能打开唯一一个任务管理器

确保一个类有一个实例且易于被访问

让类自身创建和保存他唯一的实例

定义

  1. 对象创建型模式
  2. 确保某一个类只有一个实例
  3. 必须自行创建实例——不需要用户生成
  4. 向整个系统提供这个实例

结构

单例:自己关联自己,将单例聚合到自己这个类当中,只有一个单例,因此不看作时组合关系

在这里插入图片描述

分析

  1. 构造函数必须私有化:防止其他用户实例化一个类
  2. 静态私有成员变量(自身类型):单例本身
  3. 静态公有的工厂方法:获取私有的单例

在这里插入图片描述

饿汉式单例类

什么都事先创建好了

  1. 声明就是实例化

  2. 定义为final类型

  3. 特点:

    1. 资源利用率低,加载时间长

    2. 无需考虑多线程问题

    3. 调用速度优于懒汉模式

在这里插入图片描述
在这里插入图片描述

懒汉式单例类

使用时才实例化

  1. 声明时定义为空,用户使用时才实例化,用getInstance()才实例化

  2. 特点:存在多线程调用不安全问题,在实例化的时候需要较长时间,其他进程

在这里插入图片描述

  1. 解决:使用synchronized关键字进行互斥访问

    1. 锁方法

    在这里插入图片描述

    ​ 效率低

    1. 锁代码段(问题出在于if(instance == null))
      在这里插入图片描述

      上面仍不安全,依然存在同一时间两个线程进入同一个if语句,因此要用双重检查锁定

      在这里插入图片描述

静态内部类

最优的解决方法

在这里插入图片描述

  1. 特点
    1. 延迟加载
    2. 处理多线程问题
    3. 通过双重检查锁定等机制会影响系统进程

实例

在这里插入图片描述
在这里插入图片描述

PrintSpoolerSingleton类
public class PrintSpoolerSingleton
{
   private static PrintSpoolerSingleton instance=null;
   
   private PrintSpoolerSingleton()
   {  
   }
   
   public static PrintSpoolerSingleton getInstance() throws PrintSpoolerException
   {
      if(instance==null)
      {
         System.out.println("创建打印池!");
          instance=new PrintSpoolerSingleton();     
      }
      else
      {
         throw new PrintSpoolerException("打印池正在工作中!");
      }
      return instance;
   }
   
   public void manageJobs()
   {
       System.out.println("管理打印任务!");
   }  
}
PrintSpoolerException类
public class PrintSpoolerException extends Exception    
{
   public PrintSpoolerException(String message) 
   {  
      super(message);
   }
}
Client类
public class Client
{
   public static void main(String a[])
   {
      PrintSpoolerSingleton ps1,ps2;
      try
      {
           ps1=PrintSpoolerSingleton.getInstance();
           ps1.manageJobs();  
      }
      catch(PrintSpoolerException e)
      {
              System.out.println(e.getMessage());
      }
           System.out.println("--------------------------");     
      try
      {
          ps2=PrintSpoolerSingleton.getInstance(); 
          ps2.manageJobs();   
      }
      catch(PrintSpoolerException e)
      {
          System.out.println(e.getMessage());
      }
   }
}

优点

  1. 提供了对唯一实例等受控访问
  2. 节约资源,提高性能
  3. 允许可变数目的实例(多例类),但每个实例还是只有一个——池化技术

缺点

  1. 扩展困难:没有抽象层
  2. 单例类指责过重
  3. java有自动回收机制,因此会导致单例类的丢失

适用场景

  1. 只需一个实例对象或消耗太大只允许创建一个对象
  2. 只允许一个公共访问点访问——getInstance()一个访问点:进行权限控制
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值