Head First设计模式总结(五) 单件模式

Java设计模式 专栏收录该内容
10 篇文章 1 订阅

本文基于《Head First 设计模式》一书,对单件模式进行了概括和总结

单件模式确保一个类只有一个实例,并提供一个全局访问点
有一些对象我们只需要一个,比方说:线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表(registry)的对象、日志对象,充当打印机、显卡等设备的驱动程序的对象。事实上,这类对象只能有一个实例,如果制造出多个实例,就会导致许多问题产生,例如:程序的异常行为、资源使用过量,或者是不一致的结果。

创建单件模式的步骤如下:

步骤 1

创建一个SingleObject类

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!");
   }
}
步骤 2

从Singleton类获取唯一的对象

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

执行程序,得到结果 Hello World!

下面给出几种特殊情况下的单件模式

1、懒汉式 (同步getInstance方法) (线程不安全)

特点:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程下不能正常工作。

public class Singleton{
        private static Singleton uniqueInstance ;
        private Singleton(){}
        public static synchronized Singleton getInstance(){  //同步解决了多线程的安全问题,但性能变差
            if(uniqueInstance == null){    //懒汉式,当要用时才实例化变量
                uniqueInstance = new Singleton();
            }
            return uniqueInstance;
        }
    }

//同步会降低程序的性能,同步一个方法可能会使程序的运行效率下降100倍,当getInstance方法在不频繁的地方使用时,可以同步该方法。

2、急切实例化(线程安全)
特点:这种方式比较常用,但容易产生垃圾对象。优点是没有加锁,执行效率高,缺点是类加载时就初始化了,浪费内存。

public class Singleton{
    private static Singleton uniqueInstance = new Singleton();//保证了线程安全
    private Singleton(){}
    public static Singleton getInstance(){
        return uniqueInstance;
    }
}

3、双重检查加锁
(若性能为关注的重点,那么这个方法可以提高程序性能,该方法不适用于java1.4及更早的版本)

public class Singleton{
        private static volatile Singleton uniqueInstance;
        private Singleton(){}
        public static Singleton getInstance(){
            if(uniqueInstance == null){
                synchronized(Singleton.class){
                    if(uniqueInstance == null){
                        uniqueInstance = new Singleton();
                    }
                }
            }
            return uniqueInstance;
        }
    }
    //volatile关键字确保:当uniqueInstance变量被初始化为Singleton实例时,多个线程能正确的处理uniqueInstance变量。

4、登记式(静态内部类)
特点:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。

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

5、枚举
特点:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}
  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页

打赏作者

float_yy

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值