• java设计模式1--单例模式


    1:单例模式简介

      单例模式是一种常用的软件设计模式,它确保某个类只有一个实例,而且自行实例化并向整个系统提供唯一的实例。总而言之就是在系统中只会存在一个对象,其中的数据是共享的

      特点:

        单例类只能有一个实例,所以一般会用static进行修释。

        单例类必须自己创建自己的唯一实例。也就是在类中要new一个自己。

        单例类必须向其它对象提供自己的实例。也就是要提供公共的方法获取到自己的实例对象。

      线程安全问题:

        在使用单例对象的时候,要注意单例对象里面的实例变量是会被多线程共享的,推荐将单例对象里面的实例变量使用无状态的对象,不会因为多个线程的交替调度而破坏自身状态导致线程安全问题。

    2:实现单例模式的方式

      (1)饿汉式单例(立即加载模式)

     1 //单例类--饿汉式
     2 public class Singleton{
     3     //私有的构造方法,禁止外部对其进行实例化
     4     private Singleton(){};
     5     //用static修饰唯一,这里只要Singleton类加载初始化时会new出自己的实例
     6     private static Singleton single=new Singleton();
     7     //公共的获取对象方法,在此程序中只能通过getInstance方法来获取Singleton实例
     8     public static Singleton getInstance(){
     9         return single;
    10     }
    11 }

       因为这里只要Singleton类加载的时候就创建了对象,所以不会存在线程安全问题。

      (2)懒汉式单例(延迟加载模式)

     1    //单例类--懒汉式(原始设计方式)      ps:这样可能会出现线程不安全,导致多实例
     2    public class Singleton1{
     3        //私有构造方法,禁止外部对其进行实例化
     4        private Singleton(){};
     5        //用static修饰唯一,这里只是声明了single对象等于null,并没有对其进行实例化
     6        private static Singleton single=null;
     7        //公共的获取对象方法
     8        public static Singleton getInstance(){
     9            //只有在获取的时候,而且single没有实例化时才进行实例化
    10            if(single==null){
    11                 single=new Singleton1();
    12            }
    13 14 15            return single;
    16        } 
    17   }  
     1  //单例类--懒汉式
     2  public class Singleton1{
     3      //私有构造方法,禁止外部对其进行实例化
     4      private Singleton(){};
     5      //用static修饰唯一,这里只是声明了single对象等于null,并没有对其进行实例化
     6      private static Singleton single=null;
     7      //公共的获取对象方法
     8      public static Singleton getInstance(){
     9          //只有在获取的时候,而且single没有实例化时才进行实例化
    10          if(single==null){                 //2:如是没有这个判断会导致一个线程获取single必须要等待上一个线程释放锁才能获取到对象 
    11             synchronized(Singleton1.class){      //1:同步锁,解决多个实例问题
    12                 if(single==null){
    13                      single=new Singleton1();
    14                 }
    15             }
    16          }
    17          return single;
    18      } 
    19 }

        1:同步锁:如果不实现同步的话,会导致两个线程同时运行到if(single==null)的时候,两个线程同时满足条件,都会new一个实例对象,导致会出现多个实例问题。

        2:如果不加这个判断会导致效率比较低下,一个线程获取single必须要等待上一个线程释放锁才能获取到对象。

      使用双重检查进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率

      (3)静态内部类

     1 public class Singleton2{
     2     //私有的构造方法
     3     private Singleton2(){};
     4 
     5     //静态内部类
     6     private static class InnerObject{
     7         private static Singleton2 single=new Singleton2();
     8     }
     9 
    10     public Singleton2 getInstance(){
    11         return InnerObject.single;
    12     }
    13 }

       这种方法虽然单例在多线程并发的情况下的线程安全性,但在遇到序列化对象时,在默认的方式运行得到的结果就是多例的,使用的时候需要注意。

      (4)静态代码块

    public class Singleton3{
        //私有构造方法
        private Singleton3(){}
        private static Singleton3 singleton=null;
        
        //静态代码块
        static{
            singleton=new Singleton3();
        }
        public static Singleton3 getInstance(){
            return singleton;
        }
    }

       这种方式和饿汉模式是差不多的,因为类加载完静态成员变量后会马上加载类的静态代码块

      (5)内部枚举类实现

    public class SingletonFactory {
        
        // 内部枚举类
        private enum EnmuSingleton{
            Singleton;
            private Singleton8 singleton;
            
            //枚举类的构造方法在类加载是被实例化 
            private EnmuSingleton(){
                singleton = new Singleton8();
            }
            public Singleton8 getInstance(){
                return singleton;
            }
        }
        public static Singleton8 getInstance() {
            return EnmuSingleton.Singleton.getInstance();
        }
    }
    
    class Singleton8{
        public Singleton8(){}
    }

       比较复杂,感觉在实际开发中也很少有人这样用。

    3:优缺点

      优点:系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。

      缺点:当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰,特别是看不到源码的时候。

    4:适用的场景

      需要频繁的创建和销毁的对象。

      创建对象耗时过多或者耗费资源过多,但又经常用到的对象。

      工具类对象

      频繁访问数据库或文件对象

  • 相关阅读:
    继承
    面向对象
    数据库的数据操作
    数据库数据类型以及建库语句
    第一天
    继承与多态
    C#面向对象——对象成员、方法重载、引用类库等
    C#面向对象初步
    SQL2008知识回顾
    C#知识回顾
  • 原文地址:https://www.cnblogs.com/EmilZs/p/9341345.html
Copyright © 2020-2023  润新知