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

    使用模式最好的方式是:“把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们。”

      1. 使用场景: 
        a. 产生莫对象会消耗过多的资源,为避免频繁的创建和销毁对象对资源造成的浪费。例如:

        对数据库的操作、访问IO、线程池、网络请求等。

        b. 某种类型的对象应该有且只有一个。若制造出多个这样的实例,可能导致:程序行为异常、资源使用过量、结果不一致等问题。如果多人能同时操作一个文件,又不进行版本管理,必然会有的修改被覆盖,所以:

        一个系统只能有:一个窗口管理器或文件系统,计时工具或 ID(序号)生成器,缓存(cache),处理偏好设置和注册表(registry)的对象,日志对象。

      2. 优点:减少系统开支、减少系统性能开销、避免对资源的多重占用和同时操作。
      3. 缺点:扩展困难、易引发内存泄漏、测试困难、一定程度上违背单一职责原则,进程被杀时可能有状态不一致的问题。
      4. 实现方式: 
        按加载时机分为饿汉模式和懒汉模式 
        按实现方式分为双重检查加锁、内部类和枚举方式等
      5. 定义: 
        构造函数对其他类不可见,仅仅提供一个获取唯一实例的静态方法,并且必须保证这个获取实例的方法时线程安全的,并防止反序列化、反射、克隆、多个类加载器、分布式系统等多种情况下重新生成新的实例对象。
      6. 具体实现方案: 
        懒汉模式 
        双重检测锁定方式:

    public class Singleton {
        private static volatile Singleton instance;
        private Singleton(){}
        public static Singleton getInstance(){
            if (instance==null){
                synchronized (Singleton.class){
                    if (instance==null){
                        instance=new Singleton();
                    }
                }
            }
            return instance;
        }
    }      

          该方式在1.5以下会失效。

          静态内部类:

    public class Singleton {
        private Singleton(){}
        public static final Singleton getInstance(){
            return SingletonHolder.INSTANCE;
        }
        public static class SingletonHolder{
            private static final Singleton INSTANCE=new Singleton();
        }
    }

          饿汉模式

    public class Singleton {
        private Singleton(){}
        private static final Singleton instance=new Singleton();
        public static Singleton getInstance(){
            return instance;
        }
    }

    饿汉与懒汉的比较: 
    饿汉在类加载时就已经实例化了静态对象,所以第一次调用时更快,但是在程序运行期间会一直占据一定的内存;懒汉是延时加载,优势在于资源利用率高哦,但第一次调用时的初始化工作会导致性能延时,并且在后面每次获取实例时也要先判断实例是否被初始化,造成效率损耗。

    登记式单例 
    在我们的程序中,随着迭代版本的增加,代码也越来越复杂,往往会使用到多个处理不同业务的单例,这时我们就可以采用 Map 容器来统一管理这些单例,使用时通过统一的接口来获取某个单例。在程序的初始,我们将一组单例类型注入到一个统一的管理类中来维护,即将这些实例存放在一个 Map 登记薄中,在使用时则根据 key 来获取对象对应类型的单例对象。对于已经登记过的实例,从 Map 直接返回实例;对于没有登记的,则先登记再返回。从而在对用户隐藏具体实现、降低代码耦合度的同时,也降低了用户的使用成本。

    public class SingletonManager {
        private static Map<String,Object> objectMap=new HashMap<>();
        private SingletonManager(){}
        public static void registerService(String key,Object instance){
            if (!objectMap.containsKey(key)){
                objectMap.put(key, instance);
            }
        }
        public static Object getService(String key){
            return objectMap.get(key);
        }
    }
  • 相关阅读:
    Hibernate学习笔记_关系映射
    Hibernate学习笔记_核心幵发接口及三种对象状态
    Hibernate学习笔记_联合主键
    Hibernate学习笔记_ID生成策略
    API的控制器
    MVC跨域API
    WindowsForms 调用API
    触发器
    视图
    分页的存储过程的用法
  • 原文地址:https://www.cnblogs.com/libertycode/p/6586902.html
Copyright © 2011-2022 走看看