首先来说下什么是单例模式:
举个例子吧:
就是咋们中国历史上有皇帝这一称呼,但是在一个时期内并不是每一个人都可以这样被人称呼的,那可是要杀头的!!!
同一时期只能有一个人做为我们国家的领导人(皇帝),所以这就好比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 要求生成唯一的序列号环境。