zoukankan      html  css  js  c++  java
  • 最常用的设计模式(单例模式)

      记得刚开始涉足程序的时候, 去笔试 ,发现有一个笔试题经常粗线,写一个单例模式的基本实现, 当时没研究设计模式也就不知为何物,

      到今日  , 才发现它已成为我日常开发最常用的一种设计模式。

      我写的所有设计模式的代码都会用java 呈现, 虽然第一个学习的是c++但是 最开始作为工作的是java,并且有点偏好java

      单例模式 , 意思就是 整个系统仅只有此类的一个实力, 当然这只是狭义的单例,经常看到变种的单例是允许,创建指定数量的实例的

      单例模式是一种创建型模式。 它是优化的一种策划, 避免重复创建销毁一个对象(创建销毁对象是有开销的), 有点像对象池的概念。

      

      我写博文  纯粹是对自己所了解的东西的一个回顾,  不保证权威性。  仅希望 迷途的新手能在我的博文中 有所收获,我也尽量 用我最简单的语言 去描述 我对 很多东西的理解、(这段话会在我的每一个博文里面出现 因为 我不是一个看了书 做笔记的博客, 而是我进行思考的博客 ,当然也希望大牛可以批评指正)

      下面给出一个最简单的单例的实现

     1 public class HelloSingleton {
     2     
     3     private static HelloSingleton w_Instance = new HelloSingleton();
     4 
     5     //定义一个私有的构造函数,确保在该类的外部无法生成类的实例
     6     private HelloSingleton(){
     7         
     8     }
     9     
    10     public static HelloSingleton getInst(){
    11         return w_Instance;
    12     }
    13 }

    这一种单例模式被成为饿汉模式, 其实意思就是开始的时候就实例好了 对象, 缺点是没有做到延迟加载 (延迟加载是一种优化策略,在需要的时候再去加载)这个用起来比较简便

    然后下面是 另外一种单例模式,懒汉模式

    public class HelloSingleton {
        
        private static HelloSingleton w_Instance;
    
        //定义一个私有的构造函数,确保在该类的外部无法生成类的实例
        private HelloSingleton(){
            
        }
        
        public static HelloSingleton getInst(){
            if(w_Instance == null){
                w_Instance = new HelloSingleton();
            }
            return w_Instance;
        }
    }
    public class HelloSingleton {
        
        private static HelloSingleton w_Instance;
    
        //定义一个私有的构造函数,确保在该类的外部无法生成类的实例
        private HelloSingleton(){
            
        }
        
        public static HelloSingleton getInst(){
            if(w_Instance == null){
                w_Instance = new HelloSingleton();
            }
            return w_Instance;
        }
    }

    网上看到,或者大多数人都是如此写懒汉模式的, 这种写法在单线程环境下是安全的, 但是在多线程环境下 会造成生成多个实例的问题

    比如现成A正在访问 getInst()方法 ,线程A读到w_Instance 为null ,创建该类对象并返回,线程B正好在此时也访问getInst方法,此时现成A构造的实例现成B无法看见,因为多线程环境中非同步代码快无法保证共享变量的可见性。所以该写法是有问题的, 调整为如下则不会在多线程环境下出现创建多个实例的问题。

     1 public class HelloSingleton {
     2     
     3     private static HelloSingleton w_Instance;
     4 
     5     //定义一个私有的构造函数,确保在该类的外部无法生成类的实例
     6     private HelloSingleton(){
     7         
     8     }
     9     
    10     public static synchronized HelloSingleton getInst(){
    11         if(w_Instance == null){
    12             w_Instance = new HelloSingleton();
    13         }
    14         return w_Instance;
    15     }
    16 }
     1 public class HelloSingleton {
     2     
     3     private static HelloSingleton w_Instance;
     4 
     5     //定义一个私有的构造函数,确保在该类的外部无法生成类的实例
     6     private HelloSingleton(){
     7         
     8     }
     9     
    10     public static synchronized HelloSingleton getInst(){
    11         if(w_Instance == null){
    12             w_Instance = new HelloSingleton();
    13         }
    14         return w_Instance;
    15     }
    16 }

    java用synchronized保证同步代码快。 同步代码快 既保证 变量的原子性,也保证变量的可见性。

    上面是最简单的两种单例的写法,但是为了扩展 , 还是介绍一些 其他的 常见的单例的写法。

    effective   java作者 推崇的 用枚举的方式实现的 singleton 

    1 public enum HelloSingleton {
    2     
    3     Instance;
    4     
    5 }

    额 你没有看错 就是这个样子的  , 起初 看到这个代码 , 我也很疑惑 , 这个是单例吗, 但是确实它也实现了单例 模式。 java的枚举不同于 c++ , c#等语言, java的枚举是用对象实现的, 所以此枚举里 仅有一个对象

    它的优点是这么介绍的 优点:不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象

    第四种单例,采用静态内部类型, 我的同时  很多次 跟我讲 他觉得java的内部类真的是很扯淡的设计, 不知道是干什么用的, 但是我个人感觉java的内部类让java 语言用起来更灵活, 比如我 不想让别人使用的类 仅仅想在一个对象里面使用的类 ,就可以用private 定义一个 内部类 , 别人无须知道 内部实现。 更好的实现封装的思想,

    代码示意图如下

     1 public class HelloSingleton {
     2      private static class SingletonHolder
     3      {
     4          private final static HelloSingleton w_Instance = new HelloSingleton();
     5      }
     6      
     7      private HelloSingleton(){
     8          
     9      }
    10      
    11      public static HelloSingleton getInst(){
    12          return SingletonHolder.w_Instance;
    13      }
    14 }

    此类型看起来比较晦涩  好像绕了不烧 , 这样写的好处是:加载时不会初始化静态变量INSTANCE,因为没有主动使用,达到延迟加载

    还有一个类型就不介绍了 ,因为个人 基本没用到过,   感觉自己最常用的就是第二种, 懒汉式 , 单例。

    设计模式, 单例, 就是这么简单 。 

    关于单例的变种你可以这么想 , 有的时候   你会想让单例 生成指定数量的 实例, 具体实现就是在 类里面加个 数量, 然后每次getInst 的时候去判断 是否达到最大数量, 如果达到就不在生成新的实例 ,如果没有,就生成新的实例返回, 好了 单例 就这么简单, 感觉没什么好说的 就写到这里

      

  • 相关阅读:
    Python冒泡排序(4)
    Python冒泡排序(3)
    Python3默认递归最大深度是998
    Python利用递归函数和列表推导式实现快速排序
    天池比赛的文章--欢迎大家交流
    caffe学习笔记1
    网络压缩系列1:低秩逼近
    yolov1
    Windows下用Caffe跑自己的数据(遥感影像)
    基于灰度共生矩阵的纹理提取
  • 原文地址:https://www.cnblogs.com/wzforgame/p/3740378.html
Copyright © 2011-2022 走看看