java设计模式之单例模式

单例模式是java设计模式中最简单却最常用的一种设计模式

其含义就是在全局过程中只存在一个唯一实例
即要求:

  1. 不允许外界创建本类实例对象;
  2. 不允许外界修改本类唯一实例对象;
  3. 通过本类提供的方法去获取本类唯一的实例对象。

根据上述三点要求,可以以以下三点措施应对:

  1. 将本类构造函数私有化;
  2. 在本类中创建本类“私有”,“静态”实例对象;
  3. 创建“公有”,“静态”方法返回本类唯一静态实例对象。

举个例子,我们的巨硬的Windows的任务管理器,就是这样的一个单例模式,当我们右键任务栏打开任务管理器之后,再次右键打开,就会发现,置顶显示的依旧还是当前的任务管理器,有且只有一个。
所以新建一个任务管理器类叫做TaskManager

class TaskManager{
    private static TaskManager instance=new TaskManager();//2.在本类创建静态私有实例对象;
    private TaskManager(){//1.私有化构造方法使得不能在外部创建实例;
    }
    public static TaskManager getInstance(){//3.创建公有静态方法返回唯一实例对象
        return instance;
    }
    public void showMessage(){//创建一个方法用来在main中测试本类实例对象
        System.out.println("hello");
    }
}

public static void main(string[] args){
    TaskManager tm=TaskManager.getInstance();
    tm.showMessage();
}

可以看到,在上面的代码中,在声明本类实例对象的同时直接进行了初始化,这样的方式叫做“饿汉式”,就是迫不及待的意思。

与之对应的是“懒汉式”,就是先声明,在getInstance()方法中判断如果为null,初始化之:

class TaskManager {
    private static TaskManager tm;//声明的时候并没有初始化
    // 需要把构造函数私有化,防止在类外随意创建本类对象
    private TaskManager() {
    }

    public static TaskManager getInstance(){
        // 把变量推迟初始化---懒汉式
        if (tm == null) {
            tm = new TaskManager();
        }
        return tm;
    }
}

为什么要分这两种方法

这样做的好处是什么,坏处是什么

**饿汉式–在定义变量同时初始化的方式:优点:不存在多线程并发安全问题,缺点:可能导致内存浪费;
懒汉式–把变量推迟初始化:优点:相对节省内存,缺点:存在多线程并发安全问题。(可加锁,但效率低)**

线程安全问题很好理解,因为getInstance()方法中有判断是否为null的过程,如果有两个线程,其中一个线程走到判断是否为null时为true,进去了,正准备初始化,第二个线程抢到了资源,判断发现还没来得及初始化,也为null,一顿哐哐哐运行,实例化了一个对象,然后第一个线程接着开始走剩下的路,又实例化了一个对象,很好,两个实例对象出来了,单例模式失败。

所以有了一个叫做双检锁的方法(双重校验锁)

class TaskManager{
    private volatile static TaskManager instance;
    private TaskManager(){

    }
    public static TaskManager getInstance(){
        if(instance==null){
            synchronized(TaskManager.class){
                if(instance==null){
                    instance=new TaskManager();
                }
            }
        }
        return instance;
    }
    public void showMessage(){
        System.out.println("hello");
    }
}

就是在第一次判断是否为null里面加锁之后,再加上一道判断,由于锁的连续性,不用担心第二次判断之后被抢走资源。

其实还有一种方法就是枚举!

枚举是JDK1.5之后的新特性,非常适合单例模式。

public enum TaskManager{  
    INSTANCE;  
    public void whateverMethod() {  //随便什么方法
    }  
}

就是这么简单,但是用得却非常少。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值