单例模式

首先来说下什么是单例模式:

  举个例子吧:

    就是咋们中国历史上有皇帝这一称呼,但是在一个时期内并不是每一个人都可以这样被人称呼的,那可是要杀头的!!!

  同一时期只能有一个人做为我们国家的*(皇帝),所以这就好比java中的单例模式一样,在每个应用中,指定类只能有

  一个实例。

  在java中怎么去实现它呢?

    还记得构造方法吧,我们去new一个对象的时候,其实就是调用该内的构造方法,通过构造方法创建了该类对象。好现在我们

  要做就是将构造方法私有化,这就是外部类没有访问该类的权限了。那如何获得该内的实例呢?我们总不可能让它就放在哪里成了

     摆设吧。嘿嘿,,,,我们只需要向外部提供一个共有的获取实例的方法就行了。这样就保证一个类中只能有一个实例。

package Model_Singleton;

//饿汉式单例
public class Emperor {
    //这里创建了对像,并保证了每次得到的实例是一样的
    private static final Emperor emperor=new  Emperor();
    
    private Emperor(){
        
    }

    public static Emperor getInstance(){
        return emperor;
    }
    
    public static void say(){
        System.out.println("我就是皇帝。。。。。。。。。。。。。");
    }
}
package Model_Singleton;

//懒汉式单例
public class Singleton {
    private static Singleton singleton=null;
    
    private Singleton(){
        
    }
    
    public static synchronized Singleton getSingeLeton(){
        if(singleton==null){
            singleton=new Singleton();
        }
        return singleton;
    }
    
    public  void say(){
        System.out.println("我就是皇帝。。。。。。。。。。。。。");
    }
    
}

  在这里我提供了常用的两种实现单例的方案,这两种有什么区别呢?

    1 懒汉式因为没有创建类,所以类加载的速度会快一些;但饿汉式因为已经创建实例,所以它类加载慢,获取队像快

    2 懒汉式要注意把获取实例的方法同步,否则在高并发的时候,会创建多个实例

在这里对单例模式进行扩展一下:

  还是接着上面的例子来说吧:

    上面我说一个朝代只能有一个皇帝,但大家是否记得明朝的时候曾有过这样一段时间,就是明英宗朱祁镇被俘之后,他弟弟就迫不急待的当上了皇帝,可惜

  这小子又没把他哥封为太上皇,所以就出现了一个朝代两个皇帝。这在java中有怎们去处理呢?

    

package Model_Singleton;

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

public class Emperor_number {
    //定义最多能产生的实例数量
    private static int maxNumofEmperor=2;
    //每个皇帝都有名字,使用一个ArrayList来容纳,每个对象都有私有属性
    private static ArrayList<String> nameList=new ArrayList<String>();
    //定义一个列表,容纳所有的皇帝实例
    private static ArrayList<Emperor_number> emperorList=new ArrayList<Emperor_number>();
    //当前皇帝的序列号
    private static int countNumofEmperor=0;
    //产生所有的对象
    static{
        for(int i=0;i<maxNumofEmperor;i++){
            emperorList.add(new Emperor_number("皇"+(i+1)+"帝"));
        }
    }
    
    private Emperor_number(){
        //目的不产生第二个皇帝
    }

    //传入皇帝名称,建立一个皇帝对象
    private Emperor_number(String name){
        nameList.add(name);
    }
    
    //随机获得一个皇帝对象
    public static Emperor_number getInstance(){
        Random random=new Random();
        countNumofEmperor=random.nextInt(maxNumofEmperor);
        return emperorList.get(countNumofEmperor);
    }
    
    public static void say(){
        System.out.println("我就是皇帝。。。。。。。。。。。。。");
    }
}

  这样就会的到皇帝不一样,也就是产生的实例不相同

  这种在java中叫做上限多例模式,我们可以在设计的时候决定内存中有多少个实例,方便系统扩展,提高响应速度。

最后我来总结一下自己所讲的:

 单例模式:
  通过定义一个私有的构造方法【确保了一个应用中只产生一个实例】,避免被其他类new出一个对象来。但是他本身可以new出一个自己的对象,其他类对该类的访问都是
  同过该类提供的getInstance()来获取它的实例

  优点
    1 因为在一个应用中只创建一个实例,节省了内存的开支。特别是一个对象频繁的创建和销毁的时候,它的优势就很明显了。
    2 由于单例模式只生成一个实例,所以减小了系统开销,当一个对象的产生需要比较多的资源时,如读取配置,产生其他对象的依赖,则
     可以通过在应用启动的时候直接产生一个单例对象,然后用永久驻留的方式来解决(在Java EE中采用单例模式时需要注意
    3 单例模式可以避免对资源的多重利用,例如一个写文件动作,由于只有一个实例存在内存中,避免对同一个资源文件的同时操作。
      4 单例模式可以在系统设置全局的访问点,优化和共享资源的访问,例如可以设计一个单例类,负责所有数据表的映射处理。、

  缺点
    1 单例模式一般没有接口,扩展很困难,若要扩展,基本就是修改代码。单例模式为什么没有接口,因为它要求“自行实例化”,
    ··并且提供单一的实例,接口和抽象类是不可能被实例化的
    2 单例模式与单一职责原则有冲突。

  应用场景
    在一个系统中,要求一个类仅有一个对象,如果出项多个对象就会出现不良反应,可以采用单例模式
    1 创建一个对象需要消耗的资源过多,如要访问IO和数据库等
    2 需要定义大量的静态方法和静态常量的环境,可以采用单例模式(当然,也可以直接声明为static的方式)
    3 在整个项目中需要一个共享访问点和共享数据,例如一个Web页面的计数器,可以不用把每次刷新的数据都记录到数据库中
      ,使用单利模式保存到计数器中,并确保是线程安全的
      4 要求生成唯一的序列号环境。