zoukankan      html  css  js  c++  java
  • 单例模式-Singleton Pattern

    单例模式-Singleton Pattern

      何为单例模式,举个大家都熟知的例子—— Windows任务管理器,在Windows的“任务栏”的右 键弹出菜单上多次点击“启动任务管理器”,是不能同时打开多个任务管理器窗口的。我们用代码实现下:

    假设任务管理器的类名为TaskManager,在 TaskManager类中包含了大量的成员方法,例如构造函数TaskManager(),显示进程的方法

     1 package com.feimao.singleton.test;
     2 
     3 public class TaskManager {
     4     public void displayProcess() {
     5     }
     6 
     7     public void displayServices() {
     8     }
     9 
    10     private TaskManager() {//禁止类的外部直接使用new来创建对象,所以将构造函数TaskManager()可见性改为private
    11     }
    12 
    13     public static TaskManager tm = null;//TaskManager中定义一个静态的TaskManager类型的私有成员变量,目的是为了让外界可以访问这个唯一实例
    14     public static TaskManager getInstance() {//是增加一个公有的静态方法,在类外可以直接通过类名来访问,而无须创建TaskManager对象
    15         if (tm == null) {
    16             tm = new TaskManager();
    17         }
    18         return tm;
    19     }
    20 }

      在类外我们无法直接创建新的TaskManager对象,但可以通过代码TaskManager.getInstance()来 访问实例对象,第一次调用getInstance()方法时将创建唯一实例,再次调用时将返回第一次创 建的实例,从而确保实例对象的唯一性。

      单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。

    因进程需要,有时我们只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计。

      单例模式的特点:

    1.单例模式只能有一个实例。

    2.单例类必须创建自己的唯一实例。

    3.单例类必须向其他对象提供这一实例

      单例模式VS静态类:

    在知道了什么是单例模式后,我想你一定会想到静态类,“既然只使用一个对象,为何不干脆使用静态类?”,这里我会将单例模式和静态类进行一个比较。

    1.单例可以继承和被继承,方法可以被override,而静态方法不可以。

    2.静态方法中产生的对象会在执行后被释放,进而被GC清理,不会一直存在于内存中。

    3.静态类会在第一次运行时初始化,单例模式可以有其他的选择,即可以延迟加载。

    4.基于2, 3条,由于单例对象往往存在于DAO层(例如sessionFactory),如果反复的初始化和释放,则会占用很多资源,而使用单例模式将其常驻于内存可以更加节约资源。

    5.静态方法有更高的访问效率。

    几个关于静态类的误解:

    误解一:静态方法常驻内存而实例方法不是。

    实际上,特殊编写的实例方法可以常驻内存,而静态方法需要不断初始化和释放。

    误解二:静态方法在堆(heap)上,实例方法在栈(stack)上。

    实际上,都是加载到特殊的不可写的代码内存区域中。

    静态类和单例模式情景的选择:

    情景一:不需要维持任何状态,仅仅用于全局访问,此时更适合使用静态类。

    情景二:需要维持一些特定的状态,此时更适合使用单例模式。

    单例模式的实现:

    1.懒汉模式(线程不安全)

     1 package com.feimao.a3.test;
     2 
     3 public class SingletonDemo {
     4     private static SingletonDemo instance;
     5 
     6     private SingletonDemo() {
     7 
     8     }
     9 
    10     public static SingletonDemo getInstance() {
    11         if (instance == null) {
    12             instance = new SingletonDemo();
    13         }
    14         return instance;
    15     }
    16 }

    通过提供一个静态的对象instance,利用private权限的构造方法和getInstance()方法来给予访问者一个单例。

    缺点是,没有考虑到线程安全,可能存在多个访问者同时访问,并同时构造了多个对象的问题。之所以叫做懒汉模式,主要是因为此种方法可以非常明显的lazy loading。

    针对懒汉模式线程不安全的问题,我们自然想到了,在getInstance()方法前加锁,于是就有了第二种实现。

    2.线程安全的懒汉模式(线程安全)

     1 package com.feimao.a3.test;
     2 
     3 public class SingletonDemo {
     4     private static SingletonDemo instance;
     5     private SingletonDemo(){
     6 
     7     }
     8     public static synchronized SingletonDemo getInstance(){
     9         if(instance == null){
    10             instance = new SingletonDemo();
    11         }
    12         return instance;
    13     }
    14 }

    3.饿汉模式(线程安全)

     1 package com.feimao.a3.test;
     2 
     3 public class SingletonDemo {
     4     private static SingletonDemo instance = new SingletonDemo();
     5     private SingletonDemo(){
     6 
     7     }
     8     public static  SingletonDemo getInstance(){
     9         return instance;
    10     }
    11 }

    直接在运行这个类的时候进行一次loading,之后直接访问。显然,这种方法没有起到lazy loading的效果,考虑到前面提到的和静态类的对比,这种方法只比静态类多了一个内存常驻而已。

    4.静态类内部加载(线程安全)

     1 package com.feimao.a3.test;
     2 
     3 public class SingletonDemo {
     4     private static class SingletonHolder {
     5         private static SingletonDemo instance = new SingletonDemo();
     6     }
     7 
     8     private SingletonDemo() {
     9         System.out.println("Singleton has loaded");
    10     }
    11 
    12     public static SingletonDemo getInstance() {
    13         return SingletonHolder.instance;
    14     }
    15 }
  • 相关阅读:
    idea解决Maven jar依赖冲突(四)
    代码规范:idea上添加阿里巴巴Java开发插件
    一起MySQL时间戳精度引发的血案
    JVM Code Cache空间不足,导致服务性能变慢
    通过SOFA看Java服务端如何实现运行时的模块化
    谈谈我对SOFA模块化的理解
    谈谈我对SOFA模块化的理解
    一文谈尽边缘计算
    JVM调优实战:G1中的to-space exhausted问题
    JVM调优实战:G1中的to-space exhausted问题
  • 原文地址:https://www.cnblogs.com/feimaoyuzhubaobao/p/10105995.html
Copyright © 2011-2022 走看看