1.解析
单例模式是设计模式中最简单的形式之一。一个类有且仅有一个实例,并且自行实例化向整个系统提供。
UML :
实现形式 :
(1)恶汉式
(2)懒汉式 (常用)
(3)双锁式
2.实例
恶汉式和懒汉式区别:
恶汉式 : 加载比较慢,但运行时获取对象速度快,且线程安全;
懒汉式 : 加载类时比较快,但运行时获取对象速度比较慢,且线程不安全;
恶汉式实现 :
public class Simple1Demo {
/**
* 单例模式: 恶汉式实现
*/
//1.私有化构造函数,不让其实例化 (构造函数就是为了实例化对象)
private Simple1Demo() {
}
//2.使其静态化,当类在加载的时候,就会加载对象到内存中
private static Simple1Demo simpleInstance=new Simple1Demo();
//3.创建一个公共方法,返回实例对象
public static Simple1Demo getSimple1DemoInstance(){
return simpleInstance;
}
}
懒汉式实现 :
public class Simple2Demo {
/**
* 单例模式 : 懒汉式实现
*/
//1. 私有化构造函数 ,使其不能实例化对象
private Simple2Demo (){
}
//2.声明实例名,作为返回值
private static Simple2Demo simple2DemoInstance;
//3.实现返回
public static Simple2Demo getSimple2DemoInstance(){
if(simple2DemoInstance==null){
simple2DemoInstance=new Simple2Demo();
}
return simple2DemoInstance;
}
}
双锁式实现 : 这个模式将同步内容下方到if内部,提高了执行的效率,不必每次获取对象时都进行同步,
只有第一次才同步,创建了以后就没必要了。
public static class Singleton{
private static Singleton instance=null;
private Singleton(){
//do something
}
public static Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(null==instance){
instance=new Singleton();
}
}
}
return instance;
}
}
测试 : 看不看都行
public static void main(String[] args) {
Simple1Demo simple1Demo=Simple1Demo.getSimple1DemoInstance();
Simple1Demo demo=Simple1Demo.getSimple1DemoInstance();
System.out.println("饿汉式,对象地址1:"+simple1Demo);
System.out.println("饿汉式,对象地址2:"+demo);
Simple2Demo demo2=Simple2Demo.getSimple2DemoInstance();
Simple2Demo simple2Demo=Simple2Demo.getSimple2DemoInstance();
System.out.println("懒汉式,对象地址1:"+demo2);
System.out.println("懒汉式,对象地址2:"+simple2Demo);
}
结果 :
3.优缺点
优点 :
(1)实例控制 :单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
(2)灵活性 :因为类控制了实例化过程,所以类可以灵活更改实例化过程。
缺点 :
(1)开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
(2)可能的开发混淆:使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
(3)对象生存期:不能解决删除单个对象的问题。只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。
4.应用场景
(1) 当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
(2)当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
(3)有些对象我们只需要一个的时候 ,比如 :配置文件,工具类,线程池,缓存,日志对象 等。