zoukankan      html  css  js  c++  java
  • 设计模式二 单例模式

    0、基本定义

      单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点.

    通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法,让类自身负责保存它的唯一实例。

    这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

    要求:

    1、构造私有方法

    2、定义一个实例,自己实例化

    3、获取实例

    须 解决一个并发访问的线程安全问题。

    spring 中默认bean加载都是单例。

    1、实现方式

    1.1、饿汉式

    不管用不用,先new一个对象

    public class Emperor {
    
        private static final Emperor emperor = new Emperor();
        private Emperor() {
    
        }
    
        public static Emperor getInstance() {
            return emperor;
        }
    
        public void say() {
            System.out.println("I am Empror..A. " + this);
        }
    }
    

      

    1.2、懒汉式 

    默认加载的时候不实例化,在需要用的时候,才加载

    
    
    public class Singleton {

    private static Singleton singleton = null;

    private Singleton() {}

    /**
    * 加 Synchronized, 解决 thread safe
    * 性能 差!!!
    * @return
    */
    public static synchronized LazyTwo getLazy() {
    if (lazy == null) {
    lazy = new LazyTwo();
    }
    return lazy;
    }

    }
    
    

    1.3 内部类

    /**
     *  内部类
     * @author zzf
     * @date 2018/8/25 00:14.
     */
    public class LazyThree {
    
        private static boolean initial = false;
        //默认使用LazyThree 的时候,会先初始化内部类
        //如果没有使用的话,内部类是不会加载的
        private LazyThree() {
            //
            synchronized (LazyThree.class) {
                if (initial) {
                    initial = !initial;
                } else {
                    throw new RuntimeException("单利侵入初始化");
                }
            }
        }
    
        private static final LazyThree getInstance() {
            return LazyHolder.LAZY_THREE;
        }
    
        private static class LazyHolder {
            private static final LazyThree LAZY_THREE = new LazyThree();
        }
    }

    1.4 注册登记式 

     每使用一次,都注册到容器中,下次去对象时,直接从缓存中取值,以保证每次获取的都是 同一个对象。

    Spring IOC

    /**
     * 注册式
     * @author zzf
     * @date 2018/8/25 00:25.
     */
    public class RegisterMap {
    
        private static Map<String, Object> register = new HashMap();
    
        public static RegisterMap getInstance(String name) {
    
            if (name == null) {
                name = RegisterMap.class.getName();
            }
    
            if (register.get(name) == null) {
                try {
                    register.put(name, RegisterMap.class.newInstance());
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            return (RegisterMap) register.get(name);
        }
    }

    1.5 枚举

    注册登记式的一种

    public enum RegisterEnum {
    
        INSTANCE;
    
        public static RegisterEnum getInstance() {
            return INSTANCE;
        }
    }

    1.6 序列化和反序列化

    序列化与反序列化的时候出现多例: 重写 readResolve()

    public class Seriable implements Serializable{
    
        public final static Seriable instance = new Seriable();
    
        private Seriable() {}
    
        public static Seriable getInstance() {
            return instance;
        }
    
        /**
         * jvm 实现 
         * @return
         */
        private Object readResolve() {
            return instance;
        }
    
    }

    test:

    public class SeriableTest {
    
        public static void main(String[] args) {
    
            Seriable s1 = null;
            Seriable s2 = Seriable.getInstance();
    
            FileOutputStream fos = null;
    
            try {
                fos = new FileOutputStream("seriable.obj");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(s2);
    
                oos.close();
                fos.close();
    
                ObjectInputStream ois = new ObjectInputStream(
                        new FileInputStream("seriable.obj")
                );
                s1 = (Seriable) ois.readObject();
    
                System.out.println(s1 == s2);
    }
    catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }

    2、优缺点

    2.1 、优点:

    》减少了内存开支,

    》减少了系统的性能开销,当一个对象需要较多资源时,则可以启动时直接产生。 spring IOC

    2.2、缺点

    》 单例模式一般没有接口,扩展困难

    》单例模式对测试不利。在并行环境中,如果单例没有完成,是不能进行测试的,没有接口也不能mock的方式虚拟一个对象。??why

    》与单一职责有冲突。

    2.3 使用场景

    》项目中需要一个共享数据或共享访问点,如web页面中计数器

    》 创建一个对象需要消耗的资源过多,如 访问IO和数据库等资源

    》工具类

    参考资料:

    咕泡学院

    《设计模式之蝉》

    《大话设计模式》

  • 相关阅读:
    vue Bus事件用法与bug
    移动端超出三行显示第三行显示省略号+查看全部
    Vuex
    vue点击旋转,再点击复原
    vue项目(cli-3)替换浏览器logo
    悬浮广告(二)vue版本
    悬浮广告(一)html版本
    vue下获得经纬度省市区
    一个可以输出当前移动设备机型(安卓,ios)系统版本的html页面
    谱聚类(spectral clustering)原理总结
  • 原文地址:https://www.cnblogs.com/idea-persistence/p/9532467.html
Copyright © 2011-2022 走看看