黑马程序员——JAVA设计模式之单例模式

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

JAVA设计模式之单例模式

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。
java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。
解决的问题为保证一个类在内存中的对象唯一性。
其定义为:一个类有且仅有一个实例,并且自行实例化向整个系统提供。
其特点为:
1.单例类只能有一个实例。
2.单例类必须自己创建自己的唯一实例。
3.单例类必须给所有其他对象提供这一实例。
Java单例模式例子:

public class SingletonClass{
    private static SingletonClass instance=null;//私有化构造函数
    public static SingletonClass getInstance(){//定义共有并静态的方法
        if(instance==null){
            synchronized(SingletonClass.class){
            if(instance==null){
                instance=new SingletonClass();
            }
        }
    }
    return instance;//返回该函数
    }
    private SingletonClass(){}
}

简单 单例模式的实现:
a.首先定义一个私有的变量instance来实例化类对象;
b.将构造方法私有化;
c.实现全局访问点public static Singleton getInstance()方法,而由于该方法是私有的,因此变量instance也要被定义为私有的。
d.如果实例需要比较复杂的实例化过程,那么就将实例化过程放在static{}中:

如果让其对象保持唯一性呢?就需要:
1.不让其他行星创建该类对象;
2.在本类中创建一个本类对象;
3.对外提供方法,让其他程序获取这个对象。
步骤:
1.因为创建对象都是需要构造函数初始化,只有将本类的构造函数私有化,其他程序就无法创建该类了;
2.在本类中创建一个本类对象;
3.定义一个方法返回该类(get函数),让其他程序通过get方法得到本类对象。

代码体现:
1. private函数;
2.创建并静态本类对象;
3.定义一个public static的get函数,返回该对象。

饿汉式:

public class Singleton{
    private static Singleton instance = new Singleton();//定义实例变量
    private Singleton(){};    //私有化构造方法
    public static Singleton getInstance(){//定义公有并静态的方法,返回改对象。
        return instance;
    }
}

懒汉式:

public class Singleton{
    private static Singleton instance = null;
    private Singleton(){};
    public static Singleton getInstance(){
        if(instance == null){
           instance = new Singleton();
        }
        return instance;
    }
}

懒汉式是延迟了加载方式,但器缺点是线程不安全,当多线程操作时会造成同时访问,可能会实例出多个对象。但给整个方法添加同步(public static synchronized Singleton getInstance())后虽解决了安全问题但又减低了性能。我们可以在创建的时候就加同步(private volatile static Singleton instance = null;),这样线程就可以自动的发现volatile变量的新值,一个线程实例化成功,其他线程立即发现。

public static Singleton getInstance(){
    if(instance == null){    //如果没有创建就进行同步创建
        synchronized(Singleton.class){
            if(instance == null){    //再次判断,以防两个线程同时经过第一道判断,之后先后进入同步后还是能创建各自的对象的,故需再次判断
                instance = new Singleton();
            }
        }
    }
    return instance;
}

这个就是ouble Check Locking模式
其特点为:
1.多个线程试图并发访问一个临界区;
2.临界区只需执行一次

这样还是有一个缺点就是:就是在一个线程还未完全初始化该对象时,而那个变量已经显示为被初始化,那么其他线程可能去使用这个未被完全初始化的实例,造成系统的崩溃。不过这个在java5以上可以安全运行。

另外一种完美实现的实现既线程安全又延迟加载的模式(Initialization on demand holder)使用静态内部类 示例:

Public class Singleton{
    Private Singleton(){};
    Public static class Singleton1{
        Private static final Singleton instance = new Singleton();
    }    
    Public static Singleton getInstance(){
        Return Singleton1.instance;
    }
}

这样第一次调用get方法是回去初始化被定义为static的instance实例,且只会被初始化一次。

接下去还有一个问题就是单例化类的序列化问题:如果单例类实现了serializable接口,这是要特别注意以为在默认情况下,每次反序列化时总会创建一个新的对象,注意系统就会出现多个对象了。解决方法:根据序列化可知:每次反序列化完成前都会去调用readResolve()方法,那就在该方法中,将用原对象取代新创建出来的对象。在是在该实现了序列化的类中再定义一个方法:

Public Singleton readResolve(){
    Return instance; // instance是唯一的实例对象
}

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值