确保一个类只有一个实例,并且自行实例化并向整个系统提供这一个实例。
java
主要优势:提供了对惟一实例的受控访问;因为在系统内存中只存在一个对象,所以能够节约系统资源,对于一些须要频繁建立和销毁的对象单例模式无疑能够提升系统的性能。把构造方法都隐藏了,遵循了 迪米特法则;避免对共享资源的多重占用;能够全局访问。
c++
因为单例模式中没有抽象层,所以单例类的扩展有很大的困难,违背依赖倒置原则;滥用单例将带来一些负面问题,如为了节省资源将数据库链接池对象设计为的单例类,可能会致使共享链接池对象的程序过多而出现链接池溢出,单例类的职责太重,在必定程度上违背了“单一职责原则”。数据库
适用场景:须要频繁实例化而后销毁的对象;建立对象耗时过多或者消耗资源过多,但又常常用到的对象;有状态的工具类对象;频繁访问数据库或文件的对象。安全
注意事项:多线程
只有单例类提供的方法获得单例对象,不要使用反射,不然会实例化一个新对象(也就是说经过反射是能够实例化多个单例类的),之前还听人说能够经过深拷贝,但clone方法默认是protect的,因此不用反射的话同样作不到;ide
不要作断开单例类对象与类中静态引用的危险操做(静态引用会存到java虚拟机的方法区,除非类文件被卸载,不然不会销毁,但通常类的卸载条件很严苛,因此链接静态引用的单例对象也会共存不会被gc收集);工具
多线程使用单例使用共享资源时,注意线程安全问题。性能
java中饿汉模式要好于懒汉模式,c++中则通常使用懒汉式单例。测试
有的单例能够被继承,好比登记式单例,可参考登记式单例模式。ui
单例能够有七种模式(笔者所知,不包括上述登记式单例模式):这七种模式能够参考以前转发的博文: 单例的七种表达方式
今天回家太晚了,没有把上面两篇博文整理在这里,抽空会整理的
下面代码用反射实现建立多个单例,至于问什么输出了4次,有兴趣的同窗能够看下虚拟机的类加载机制。各位晚安。
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class clazz=Class.forName(SingleTon.class.getName()); Constructor constructor=clazz.getDeclaredConstructors()[0]; constructor.setAccessible(true); constructor.newInstance(new Object[]{}); constructor.newInstance(new Object[]{}); constructor.newInstance(new Object[]{}); } } class SingleTon{ private static SingleTon singleTon=new SingleTon(); private SingleTon(){ System.out.println("chuangjian"); } public static SingleTon getInstance(){ return singleTon; } }