设计模式之单例模式

单例模式

单例模式是设计模式中最简单的形式之一。这一模式的目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例).

特点

优点:
(1) 由于单例模式在内存中只有一个实例,减少内存开支,特别是一个对象需要频繁地创建销毁时,而且创建或销毁时性能又无法优化,单例模式就非常明显了

(2) 由于单例模式只生成一个实例,所以,减少系统的性能开销,当一个对象产生需要比较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。

(3) 单例模式可以避免对资源的多重占用,例如一个写文件操作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作

(4) 单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如,可以设计一个单例类,负责所有数据表的映射处理。

缺点:
(1) 单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。

(2) 单例对象如果持有Context,那么很容易引发内存泄漏,此时需要注意传递给单例对象的Context最好是Application Context。

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

使用场景

1、要求生产唯一序列号。
2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

注意事项: getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

public class singleObject {
    private static singleObject object = new singleObject();

    private singleObject() {

    }

    public static singleObject getInstance() {
        return object;
    }

    public void print() {
        System.out.println("你好啊!");
    }

}
class demo{

    public static void main(String[] args) {
//        singleObject ob=new singleObject();//会编译错误
        singleObject ob=singleObject.getInstance();
        ob.print();
    }
}

单例模式的实现方式

1.懒汉模式,线程不安全
//懒加载 (懒加载其实就是延时加载,即当对象需要用到的时候再去加载),线程不安全
public class single1 { //懒汉模式 线程不安全
private static single1 object;
private single1(){};
public static single1 getInstance(){
    if(object==null){
        object=new single1();
    }
    return object;
}
}
2.懒汉模式 线程安全

这种方式具备很好的懒加载,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。

优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。

//懒加载 线程安全
public class single2 {//懒汉模式  线程安全
    private static single2 object;
    private single2(){};
    public static synchronized single2 getInstance(){
        if(object==null){
            object=new single2();
        }
        return object;
    }
}
3.饿汉模式 线程安全

这种方式比较常用,但容易产生垃圾对象。

优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。

它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到懒加载.

//不懒加载
public class single3 {  //饿汉模式   线程安全
    private static single3 object=new single3();
    private single3(){};
    public static single3 getInstance(){
        return object;
    }
}
4.双重校验锁

这种方式采用双锁机制,安全且在多线程情况下能保持高性能

public class single4 {//双重校验锁
    private static volatile single4 object;
    private single4(){};
    public static single4 getInstance(){
        if (object==null){
            synchronized (single4.class){
                if (object==null){
                    object=new single4();
                }
            }
        }
        return object;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值