当程序运行时,有时会希望在程序中,只能存在一个实例,为了达到目的,所以设计了Singleton模式,即单例模式。
单例模式的特征:
- 想确保任何情况下只存在一个实例
- 想在程序上表现出只存在一个实例
示例程序:
- Singleton单例类
package site.wangxin520.gof.singleton; /** * 单例模式获取单例对象的类 * @author wangXgnaw * */ public class Singleton { //将创建出来的对象设为静态的私有对象 private static Singleton singleton=new Singleton(); //将构造方法私有化,不允许外部类中使用new 去创建对象 private Singleton(){} //对外提供一个静态方法,获取到对象,因为对象是静态的私有属性 //所以是随着类的加载而加载的,并且只加载一次,这样一来,就只返回同一个对象了 public static Singleton getInstance(){ return singleton; } }
- Singleton单例测试程序
package site.wangxin520.gof.singleton; /** * 单例模式的测试类 * @author wangXgnaw * */ public class SingletonTest { public static void main(String[] args) { //使用getInstance获取实例化的方法,创建两个对象 Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); //==双等号,在判断对象的时候,是比较对象的地址值,如果地址值为一样的话,那么就代表,单例模式创建成功。 if (s1==s2) { System.out.println("单例模式创建成功"); }else { System.out.println("单例模式创建失败"); } } }
- 测试结果:
在单例模式中,需要注意的是,多线程情况下单例模式可能存在的问题,这里不做讨论。还有就是static关键字的用法——静态随着类加载而加载,且只加载一次。
补充一个测试练习题:
编写Triple类,实现最多只能生成三个实例,实例编号为0,1,2,并且可以通过getInstance(int id)方法来获取到该编号对应的实例:
- Triple类
package site.wangxin520.gof.singleton; import java.util.ArrayList; public class Triple { //建立一个静态的数组,用于保存创建的实例 private static ArrayList<Triple> arr=new ArrayList<Triple>(); //属性id private int id; //私有化构造函数 private Triple(){} //通过id去获取对应的实例 public static Triple getInstance(int id){ try{ //尝试从静态数组中获取,这里采用的是try catch接异常的方法 Triple triple = arr.get(id); //如果数组中存在所需要的,那么就直接返回,否则抛异常 return triple; }catch(Exception e){ //调用getInstance()方法进行操作 return getInstance(); } } //没有参数,就不会造成异常的产生 public static Triple getInstance(){ //判断是否创建超过了3 if(arr.size()<3){ Triple t=new Triple(); t.id=arr.size(); arr.add(t); return t; }else{ //如果创建超过了3个,那么就返回第一个实例s return getInstance(0); } } }
- 测试类
package site.wangxin520.gof.singleton; public class TripleTest { public static void main(String[] args) { Triple t1 = Triple.getInstance(); Triple t2 = Triple.getInstance(); Triple t3 = Triple.getInstance(); Triple t4 = Triple.getInstance(); System.out.println(t1==t2); System.out.println(t1==t3); System.out.println(t1==t4); System.out.println(t2==t3); System.out.println(t2==t4); System.out.println(t3==t4); } }
- 结果
可见t1和t4是相同的,因为超过三个了,就直接返回第一个,getInstance()方法正常
- 测试2
package site.wangxin520.gof.singleton; public class TripleTest { public static void main(String[] args) { Triple t1 = Triple.getInstance(0); Triple t2 = Triple.getInstance(1); Triple t3 = Triple.getInstance(2); Triple t4 = Triple.getInstance(3); System.out.println(t1==t2); System.out.println(t1==t3); System.out.println(t1==t4); System.out.println(t2==t3); System.out.println(t2==t4); System.out.println(t3==t4); } }
- 结果
同样的,当想要获取编号不在0,1,2三个里面的话,就会返回第0个,所以t4和t1是相同的。