JAVA设计模式之单例模式

来源:互联网 发布:韩国idol和演员 知乎 编辑:程序博客网 时间:2024/06/14 17:59

概念

单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中应用该模式的类只有一个实例。即一个类只有一个对象实例。

实现

第一步:将类的构造函数声明为私有的构造函数,这样我们在外部就无法通过new来实例化该类,这样可以保证类的实例只有一个(那就是在类的内部给它实例化)。
第二步:在类的里面声明一个公开的全局的静态字段(其实也就是提供一个全局的访问点),外部对象通过这个访问点可以拿到该类的唯一实例。切记,该字段必须声明成static静态段,如果声明成非静态字段,那在类的外部就访问不到了。因为非静态成员只能通过类的实例去访问,而我们在类的外部是无法对该类进行实例化的。

懒汉式单例类

class SingleInstance {    private static SingleInstance instance=null;    //在接口被调用的时候创建对象    public static SingleInstance getInstance(){        if(instance==null){               instance=new SingleInstance ();        }        return instance;    }    //构造器私有化    private SingleInstance(){    }}

小结:该种方式优点在于调用接口时才实例化对象,所以节约内存资源,但是却存在线程安全的问题。

线程安全的懒汉式单例(双重锁)

public class SingleInstance {    private volatile static SingleInstance single;    //构造器私有化    private SingleInstance(){};    //对外接口    public static SingleInstance getSingle(){        if(single==null){            synchronized(SingleInstance.class){                if(single==null){//二次检查                    single=new SingleInstance();                }            }        }        return single;    }}

测试类:

public class Test9 implements Runnable{    public static void main(String[] args) {        //同时启动两个线程进行访问        Test9 test=new Test9();        Thread t=new Thread(test);        Thread t1=new Thread(test);        t.start();        t1.start();    }    @Override    public void run() {        // TODO Auto-generated method stub        for(int i=0;i<10;i++){            SingleInstance s=SingleInstance.getSingle();            System.out.println(s);        }    }}

输出结果:
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321

小结:该种方式只在某些重要的代码上加锁即保证了线程安全又提高了效率。

饿汉式单例类

public class SingleInstance {    private static SingleInstance s;    //利用静态初始化生成类实例    static{        s=new SingleInstance();    }    //构造方法私有化,防止外部实例化对象    private SingleInstance(){};    //提供公共访问接口    public static SingleInstance getS(){        return s;    }}

测试输出结果:
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321
cn.zy.test.SingleInstance@4eb09321

小结:该种方式的优点在于对象是在类加载时即创建,因此不需要考虑线程安全的问题,缺点是提前占用系统资源。

总结

单例模式虽然简单但是却最常用,稍有不慎却容易出错,对于以上两种方案个人偏向于第二种实现,虽然提前耗费点资源,但代码却变得简洁,由于不用考虑并发因此该种方法不易出错。

原创粉丝点击