【设计模式(二)】创建型模式之单例模式

本文详细介绍了Java设计模式中的单例模式,包括其目的、应用场景和五种常见实现方式:懒汉式、饿汉式、双重锁模式、静态内部类和枚举模式。讨论了各实现方式的优缺点,线程安全问题以及如何防止单例模式被破坏。着重分析了双重锁模式的volatile关键字作用和枚举模式的防破坏机制。
摘要由CSDN通过智能技术生成

个人学习笔记分享,当前能力有限,请勿贬低,菜鸟互学,大佬绕道

如有勘误,欢迎指出和讨论,本文后期也会进行修正和补充


前言

单例模式是Java最简单和常见的模式之一

都知道Java中,类需要被实例化为对象才能使用,因而同一个类可以被实例化为多个对象,但是部分场景我们需要使用同一个对象,这就是单例模式出现的原因


1.介绍

使用目的:保证一个类仅有一个实例,并提供一个访问他的全局访问点

使用时机:需要节省系统资源,或者需要在多个地方公用类里面的数据等情况

解决问题:频繁创建和销毁实例导致资源浪费,同一个类的不同实例的数据互不公用

实现方法:单例类通过私有构造函数创建唯一实例,并提供公共访问点给其他对象

  • 单例类只能有一个实例
  • 单例类必须自己创建自己的唯一实例
  • 单例类必须给所有其他对象提供这一实例

应用实例:

  • 全局管理器,如手机app里下载管理器,只能有一个管理器,负责调控真个app的下载任务
  • 命令池等公用对象,需要公用里面的数据,那么显然只能创建唯一实例并提供给其他对象
  • 消耗资源较多的实例,如后端需要发送http请求,若频繁创建client则会消耗大量资源,那么不妨将该实例作为单例,每次都是用同一个client

优点

  1. 仅有一个实例,那么避免了频繁创建和销毁带来的资源消耗
  2. 实例公用,那么可以保证不同对象可以使用同一份数据
  3. 实例由类自身持有,那么不会因为无人持有而销毁,从而达到数据持久化的目的

缺点:没有接口,不能继承,自己创建自己的实例,与单一职责原则冲突(一个类应该只关心内部逻辑,而不关心外面怎么样来实例化)


2.实现

2.1.基本步骤

  1. 定义私有构造函数,那么该类将不会被其他对象实例化

       private SingleObject(){
         }
    
  2. 自己创建实例化对象

       private static SingleObject instance = new SingleObject();
    
  3. 定义全局访问点,提供给其他对象

       public static SingleObject getInstance(){
         
          return instance;
       }
    
  4. 定义类相关业务代码

       public void showMessage(){
         
          System.out.println("Hello World!");
       }
    

完整代码

public class SingleObject {
   
 
   //创建 SingleObject 的一个对象
   private static SingleObject instance = new SingleObject();
 
   //让构造函数为 private,这样该类就不会被实例化
   private SingleObject(){
   }
 
   //获取唯一可用的对象
   public static SingleObject getInstance(){
   
      return instance;
   }
 
   public void showMessage(){
   
      System.out.println("Hello World!");
   }
}
  1. 在其他对象中获取实例,并调用相关业务方法

    public class SingletonPatternDemo {
         
       public static void main(String[] args) {
         
     
          //不合法的构造函数
          //编译时错误:私有构造函数 SingleObject() 不可见的
          //SingleObject object = new SingleObject();
     
          //获取唯一可用的对象
          SingleObject object = SingleObject.getInstance();
     
          //显示消息
          object.showMessage();
       }
    }
    

2.2.五种常见实现方案

2.2.1.懒汉式

第一次被调用时初始化,节省资源,但线程不安全,

基于“懒“的思想实现,即被动初始化,如果不被使用就不会被初始化

私有构造器和一个公有静态工厂方法构成,在工厂方法中对singleton进行null判断,如果是null就new一个出来,最后返回singleton对象

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

该方法的优点是节省了资源,如果不需要被使用,就不会初始化,只有第一次使用才会生成实体对象

而缺点很明显,就是线程不安全,如果两个方法同时调用Singleton.getInstance(),就可能重复生成对象

如果对Singleton.getInstance()加上同步锁即可解决线程不安全的问题,但是代价是每次调用都会产生不必要的同步开销

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值