Java设计模式之单例模式

设计模式

1.概述

  设计模式其实就是前人解决问题所总结(所使用)的方法。被后人所整理的一些方法。

2.单例设计模式

A.概述
   所谓单例是指一个类只能实例化一个对象。
B.实现方式
   1.定义私有静态成员变量(变量类型与当前自定义类型相一致)
   2.私有化构造函数(避免直接实例化对象)
   3.公共静态方法(用于返回实例对象)
C.实现方式
   1.懒汉式
   2.饿汉式

3.代码实现

懒汉模式
class SingleClass{
    //懒汉式
    //懒汉式不直接进行实例化,实例化操作在静态方法中进行
    //缺点:在静态方法中需要进行判断(造成一定的时间上的消耗)
    //适用:类的使用不频繁,具体实例化时间不确定的情况
    private static SingleClass instance = null;

    //定义私有的构造函数(避免直接调用构造函数实例化对象)
    private SingleClass() {
        System.out.println("构造函数被调用,Date:" + new Date().toLocaleString());
    }

    //提供公共的静态方法用于实例化对象
    public static SingleClass createInstance(){
        //判断当前对象是否为null
        //(如果为null则实例化对象,否则直接返回instance变量)
        if(instance == null)
            instance = new SingleClass();           
        return instance;
    }
}
饿汉模式
class SingleClass{
    //定义静态成员变量用于存储当前类型的实例
    //饿汉式
    //饿汉式直接进行对象的实例化
    //缺点:直接实例化会造成资源浪费
    //适用:类的使用较为频繁的情况
    private static SingleClass instance=new SingleClass();


    //定义私有的构造函数(避免直接调用构造函数实例化对象)
    private SingleClass() {
        System.out.println("构造函数被调用,Date:" + new  Date().toLocaleString());
    }

    //提供公共的静态方法用于实例化对象
    public static SingleClass createInstance(){     
        return instance;
    }
}

1. 补充

对于以上两种单例模式的实现,事实上通过java的反射机制是能够实例化为private的类的,那基本上会使所有的java单例的实现失效,在这里我们不考虑java的反射机制。

但是此外以上的懒汉式实现的单例模式没有考虑线程安全性问题,他是线程不安全的,并发环境下可能出现多个SingleClass的实例,要实现线程安全,有以下几种方式:

什么是线程安全?

在多线程环境下,执行同一段代码或者变量结果都是相同的,我们就称为线程安全的,反之则为非线程安全的,线程不安全的。

1.在createInstance()方法上加同步

 public static synchronized SingleClass createInstance(){
        if(instance == null)
            instance = new SingleClass();           
        return instance;
 }

2.双重检查锁定

public static SingleClass createInstance(){
        if(instance==null){
            synchronized (SingleClass.class) {
                if(instance==null){
                    instance = new SingleClass();
                }
            }
        }   
        return instance;
}

3.静态内部类

class SingleClass{
    private SingleClass(){}
    private static class Lazy{
        private static final SingleClass INSTANCE = new SingleClass();
    }
    public static final SingleClass createInstance(){
        return Lazy.INSTANCE;
    }   
}

这种方式要比前两种好些,即实现了线程安全,有避免了同步带来的性能影响。

1、2、3三种实现又有何区别?

1种,在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的,

第2种,在createInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗

第3种,利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗。

对于饿汉式,它在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值