23种设计模式----------单例模式.

时间:2022-09-09 08:36:49

目前,在看一本设计模式之禅的一本书(电子版),感觉写的还不错,语音也挺幽默的,例子也有代表性,

所以,就想在看后有个更深印象,也顺便记录下学习之旅,是用的语音也是Java.

第一个,当然是单例模式:

所谓单例,当然就是只有一个实例.不允许该类创建出多个实例对象.

我们都知道,一般我们创建一个对象,直接使用new关键字,然后调用对应参数的构造方法创建实例对象.

例如:

//例如我们有各类为Singleton
public class Singleton {
    
}
//所以一般情况我们创建实例对象的方式为:
Singleton single = new Singleton();

 

所以,

1,当我们把一个类的构造方法私有化,外部就不能创建该对象(至少不能使用new关键字).

2,不过,既然创建出了个类,我们就是为了用他的,所以,要在内部创建好实例,并给出一个静态方法来获取该类的实例(毕竟我们这个类的构造方法私有化了).

3,同时,在该类中创建的实例,一定是不可修改的,不然就不是单例了,故应该将该类创建的实例,定义为 static final的,使该实例不能修改,确保一旦创建出,就是唯一的.

代码如下:

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

 基本上只要符合这种要求,单例模式就出炉了.

一般,单例模式有两种实现方式.上面那种为 饿汉式(在类加载的时候就将该实例对象创建好,等待别人获取).

另一种为懒汉式(在别人第一次访问的时候再将对象实例创建).

public class Singleton {
    
    private Singleton(){
        
    }
  
private static Singleton single = null; public static Singleton getInstance(){ if(single!=null){ single = new Singleton(); } return single; } }

这两种实现方式最重要的区别在于该单例类何时实例化.

饿汉式为在类加载的时候就创建好实例.

而懒汉式则在其他类第一次访问的时候再进行创建.

 

不过,懒汉式,由于在创建实例的时候,并不是,立即创建,而是需要判断是否已经存在实例了,

所以,在此处很有可能存在线程安全问题.

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

所以,但看这两种实现方式,明显懒汉式每次在别人访问拿实例的时候,都需要进行同步,

这样,无疑会使得相对消耗cpu资源多一些,毕竟每次只有访问完成后才将锁释放掉.

所以,一般使用单例模式,比较推荐使用饿汉式,1,代码简洁.2,消耗小.

不过单例模式,由于只能存在一个对象,所以,很容易出现并发问题.

所以,系统中,有时会考虑有上限的多例模式.

import java.util.ArrayList;
import java.util.Random;

public class MultiInstance {
    
    private MultiInstance(){
        
    }
    
    private static int maxNumOfInstance = 4;
    
    //创建一个集合来装载这些实例
    private static ArrayList<MultiInstance> instances = new ArrayList<MultiInstance>();
    
    //利用静态代码块加载所需要的实例
    static {
        for(int i=0; i<maxNumOfInstance; i++){
            instances.add(new MultiInstance());
        }
    }
    
    //随即获取一个实例对象
    public static MultiInstance getInstance(){
        int number = new Random().nextInt(maxNumOfInstance);
        return instances.get(number);
    }
    
}

单例模式在23中设计模式中算是比较简单的一种,应用也是比较广泛的,比如在spring中,每一个Bean都是默认为单例的.

不过在使用单例模式的时候,需要注意,若我们这个单例对象长时间不使用,JVM可能会认为该实例为一个垃圾,在cpu空闲的时候将其回收,

我们下次再次调用产生的对象,就会是一个新的实例.所以,若该实例,是有记录信息,或者状态的时候,一定要谨慎使用单例模式.