解决:保证了一个类在内存中只能有一个对象。
思路:
1、如果其他程序能够随意用new创建该类对象,那么就无法控制个数。因此,不让其他程序用new创建该类的对象。
2、既然不让其他程序new该类对象,那么该类在自己内部就要创建一个对象,否则该类就永远无法创建对象了。
3、该类将创建的对象对外(整个系统)提供,让其他程序获取并使用。
步骤:
1、将该类中的构造函数私有化。
2、在本类中创建一个本类对象。
3、定义一个方法,返回值类型是本类类型。让其他程序通过该方法就可以获取到该类对象。
饿汉式:
/** * Time:2018/4/13 * Description:单例---饿汉模式 * @author 宋进宇 */ public class HungryManModel { //加载类模板时就加载实例。 private static final HungryManModel HUNGRY_MAN_MODEL = new HungryManModel(); //私有化构造方法,以便实现单例 private HungryManModel(){ } //获取实例 public static HungryManModel getInstance(){ return HUNGRY_MAN_MODEL; } }
懒汉式:
/** * Time:2018/4/13 * Description:单例---懒汉模式 * @author 宋进宇 */ public class LazyManModel { //加载类模板时不加载实例,到调用获取实例方法时,在实例化对象 private static LazyManModel lazyManModel = null; //私有化构造函数,以便实现单例 private LazyManModel(){ } //提供一个获取实例的方法 //★★★在多线程的情况中需要用 synchronized 关键字 对该方法加锁。 public synchronized static LazyManModel getInstance() { //如果是第一次调用获取实例方法,则创建一个对象,否则直接返回lazyManModel if (lazyManModel==null) { lazyManModel = new LazyManModel(); } return lazyManModel; } }
单例变形---多例
不限个数“单例+缓存”:
缓存在编程中使用很频繁,有着非常重要的作用,它能够帮助程序实现以空间换取时间,通常被设计成整个应用程序所共享的一个空间,现要求实现一个用缓存存放单例对象的类。
说明:该缓存中可以存放多个该类对象,每个对象以一个key值标识,key值相同时所访问的是同一个单例对象。
import java.util.HashMap; import java.util.Map; /** * Time:2018/4/14 * Description:多例---不限个数 * @author 宋进宇 */ public class MultiCase { //一加载类模板时,就创建一个map容器 private static Map<String, MultiCase> multiCases = new HashMap<String, MultiCase>(); //看项目需求,是否需要封掉构造函数,本例采用封掉构造函数 private MultiCase(){ } //对外提供一个可以通过key来获取一个对象实例 public static MultiCase getInstanceByKey(String key) { //先通过key从容器中获取一个值 synchronized (key) { MultiCase value = multiCases.get(key); //如果是null说明该对象还没被实例化,即第一次通过这个key值来获取实例 if (value==null) { value = new MultiCase(); multiCases.put(key, value); } return value; } } }
限制个数“单例+缓存+控制实例个数”:
把上面缓存的单例实现,做成一个能够控制对象个数的共享空间,供整个应用程序使用。在缓存中维护指定个数的对象,每个对象的key值由该类内部指定,有外部请求时直接返回其中一个对象出去。
说明:相当于维护一个指定数量的对象池,当请求个数超过控制的总数时,开始循环重复使用 。
import java.util.HashMap; import java.util.Map; /** * Time:2018/4/14 * Description:多例---不限个数 * @author 宋进宇 */ public class MultiCase2 { //一加载类模板时,就创建一个map容器 private static Map<Integer, MultiCase2> multiCase2s = new HashMap<Integer, MultiCase2>(); //设置该容器中最多的实例个数 private final static int MAX = 3; private static int num = 0;//已使用个数 //封掉构造函数 private MultiCase2(){ } //对外提供一个可以获取一个对象实例的方法 public static MultiCase2 getInstance(){ MultiCase2 value = multiCase2s.get(num); if (value==null) { value = new MultiCase2(); multiCase2s.put(num, value); } num++; if (num>MAX) { //根据项目来控制,本例直接清0 num = 0; } return value; } }