• java设计模式-单例模式


    模式导读:

    单例模式:保证一个类只有一个实例,并且能够提供一个访问该实例的全局访问点。

    优点:由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决。

    单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。

    参考类图:

    代码实现:

    常见的五种单例模式实现方式:

    主要:

      饿汉式:线程安全,调用效率高,不能延时加载。

     1 package com.etc;
     2 
     3 //饿汉式单例模式,不可延时加载,调用效率高
     4 public class HungrySingleton {
     5     // 类初始化时立即加载这个对象,加载类时天然的是线程安全的
     6     private static HungrySingleton instance = new HungrySingleton();
     7 
     8     // 让构造器为 private,这样该类就不会被实例化
     9     private HungrySingleton() {
    10     }
    11 
    12     // 获取唯一可用的对象,方法没有同步,调用效率高
    13     public static HungrySingleton getInstance() {
    14         return instance;
    15     }
    16 
    17     public void showMessage() {
    18         System.out.println("饿汉式单例模式测试输出:立即加载!");
    19     }
    20 }

     懒汉式:线程安全,调用效率不高,可以延时加载。

     1 package com.etc;
     2 //懒汉式单例模式
     3 public class LazySingleton {
     4     //类初始化时,不初始化对象,延时加载
     5     private static LazySingleton instance=null;
     6     //私有化构造器
     7     private LazySingleton() {
     8         
     9     }
    10     //设置了方法同步,每次调用该方法都要同步,并发效率低,资源利用率高
    11     public synchronized static LazySingleton getInstance() {
    12         //当需要使用时再初始化类对象
    13         if(instance==null) {
    14             instance=new LazySingleton();
    15         }
    16         return instance;
    17     }
    18     public void showMessage() {
    19         System.out.println("懒汉式单例模式测试输出:延时加载!");
    20     }
    21 }

    其他:

     双重检测锁式:由于JVM底层内部模型原因,偶尔会出问题,不建议使用。

     1 package com.etc;
     2 //双重检测锁式单例模式
     3 public class DCClockSingleton {
     4 
     5     public static DCClockSingleton instance=null;
     6     //私有化构造器
     7     private DCClockSingleton() {
     8 
     9     }
    10     //将同步内容下放到if内部,提高了执行的效率,不必每次获取对象都进行同步,只有第一次才同步创建了以后就不必同步
    11     public static DCClockSingleton getInstance() {
    12         if(instance ==null) {
    13             DCClockSingleton ds;
    14             //第一重检测锁
    15             synchronized(DCClockSingleton.class) {
    16                 ds=instance;
    17                 if(ds==null) {
    18                     //第二重检测锁
    19                     synchronized(DCClockSingleton.class) {
    20                         if(ds==null) {
    21                             ds=new DCClockSingleton();
    22                         }
    23                     }
    24                     instance=ds;
    25                 }
    26             }
    27         }
    28         return instance;
    29     }
    30     public void showMessage() {
    31         System.out.println("双重检测锁单例模式测试输出:延时加载!");
    32     }
    33 }

      静态内部类式:线程安全,调用效率高,可以延时加载。

     1 package com.etc;
     2 //静态内部类单例模式
     3 public class StaticNativeClassSingleton {
     4     //私有化构造器
     5     private StaticNativeClassSingleton() {
     6     }
     7     //静态内部类,实现类的延时加载
     8     private static class InstanceSingleton{
     9         private static final StaticNativeClassSingleton instance=new StaticNativeClassSingleton();
    10     }
    11     //方法未同步,效率高
    12     public static  StaticNativeClassSingleton getInstance() {
    13         return InstanceSingleton.instance;
    14     }
    15     public void showMessage() {
    16         System.out.println("静态内部类单例模式测试输出:延时加载!");
    17         
    18     }
    19 }

      枚举单例:线程安全,调用效率高,不能延时加载。

    1 package com.etc;
    2 //枚举单例模式
    3 public enum EnumSingleton {
    4     //枚举元素本身就是代表单例对象
    5     instance;
    6     public void showMessage() {
    7         System.out.println("枚举单例模式测试输出:立即加载!");
    8     }
    9 }

    ps:测试类

     1 package com.etc;
     2 
     3 public class SingletonTest {
     4 
     5     public static void main(String[] args) {
     6         //饿汉式单例模式测试输出
     7         HungrySingleton hungry=HungrySingleton.getInstance();
     8         hungry.showMessage();
     9         //懒汉式单例模式测试输出
    10         LazySingleton lazy=LazySingleton.getInstance();
    11         lazy.showMessage();
    12         //双重检测锁单例模式测试输出
    13         DCClockSingleton dcclock=DCClockSingleton.getInstance();
    14         dcclock.showMessage();
    15         //静态内部类单例模式测试输出
    16         StaticNativeClassSingleton sns=StaticNativeClassSingleton.getInstance();
    17         sns.showMessage();
    18         //枚举单例模式测试输出
    19         EnumSingleton e=EnumSingleton.instance;
    20         e.showMessage();
    21         
    22     }
    23 }

    效果截图:

    单例模式优缺点:

    优点:

    1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。
    2、避免对资源的多重占用。

    缺点:

    没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

    适用场景:

    1、要求生产唯一序列号。
    2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
    3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

     

  • 相关阅读:
    第13篇-通过InterpreterCodelet存储机器指令片段
    第12篇-认识CodeletMark
    第11篇-认识Stub与StubQueue
    第10篇-初始化模板表
    第9篇-字节码指令的定义
    Java虚拟机漫漫学习路,我终于悟了
    Unity真机连接profiler
    提取图片中文字方法
    登录锁定个人收藏代码
    java判断密码是否为复杂类型(同时包含大小写和数字)
  • 原文地址:https://www.cnblogs.com/weekstart/p/singleton.html
Copyright © 2020-2023  润新知