1.单例设计模式

1.单例设计模式

a.概述

  • 单例设计模式是指某个类只有一个实例的设计模式。
  • 特点:
      • 1.构造函数是private修饰的,目的是防止用户调用构造函数创建对象
      • 2.类的内部有静态工厂方法,返回该类的唯一实例。
      • 3.类的唯一实例被private staic修饰的引用所修饰    

b.单例分类

  • 饿汉单例
  • /**
     * Created by yangyun on 2017/2/23.
     */
    public class SingletonTest {
        //饿汉单例在类初始化的时候创建实例
        private static SingletonTest instance=new SingletonTest();
    
        private SingletonTest(){}
    
        public static SingletonTest getInstance(){
            return instance;
        }
    }
    
  • 特点:
      • 优点:天生就是线程安全的,不用进行同步的处理
      • 缺点:类加载的初始化阶段,会把类的staic字段放在clinit函数中进行执行,也就会初始化类的单例,这样做的缺点是无论是否会用到这个单例都会产生这个实例,有时候会浪费空间。
  • 懒汉单例
  • public class SingletonTest {
        //饿汉单例在类初始化的时候创建实例
        private static SingletonTest instance;
    
        private SingletonTest(){}
    
        public synchronized static SingletonTest getInstance(){
            if(instance==null){
                instance=new SingletonTest();
            }
            return instance;
        } 
    }
  • 特点:
      • 优点:考虑了线程安全,在特定的情况下可以节约内存
      • 缺点:同步会影响效率,整个函数都是同步的,每次调用都需要等待其他线程释放锁
  • 懒汉单例------改进
  • 改进:仅仅同步创建对象的代码块
  • public class SingletonTest {
        //饿汉单例在类初始化的时候创建实例
        private static SingletonTest instance;
    
        private SingletonTest(){}
    
        public static SingletonTest getInstance(){
    
            if(instance==null) {
                synchronized (SingletonTest.class) {
                    if (instance==null) {
                        instance = new SingletonTest();
                    }
                }
            }
            return instance;
        }
    }  
  • 为什么两次判断instance==null
  • 假设有两个线程在第一次判断后都为true,线程A先获取了对象锁,创建了对象后释放锁
  • 第二个线程获取锁后,进行第二次instance==null的检查后,避免再次创建对象

c.反射与单例

  • /**
     * Created by yangyun on 2017/2/23.
     */
    public class SingletonTest {
        //饿汉单例在类初始化的时候创建实例
        private static SingletonTest instance;
    
        private SingletonTest(){}
    
        public static SingletonTest getInstance(){
    
            if(instance==null) {
                synchronized (SingletonTest.class) {
                    if (instance==null) {
                        instance = new SingletonTest();
                    }
                }
            }
            return instance;
        }
    
        public static void main(String[] args){
            try {
                SingletonTest instance1=SingletonTest.class.newInstance();
                SingletonTest instance2=SingletonTest.getInstance();
                System.out.println(instance1);
                System.out.println(instance2);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }//instace1、instance2的地址是不一样的,是两个对象
  • 说明:
  • 通过放射,可以调用类的构造函数,即使是private构造函数也是可以的
  • 所以说在反射面前所有的单例设计模式都是失效的。

 

posted @ 2017-02-23 12:01  疯狂的肉包  阅读(156)  评论(0编辑  收藏  举报