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

来源:互联网 发布:程序编程培训 编辑:程序博客网 时间:2024/05/07 01:59

——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
原创粉丝点击