1、定义:确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
2、代码示例
只有一个实例的单例
/** * 皇帝类 */ 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("我就是皇帝某某某...."); } }
/** * 臣子类 */ public class Minister { public static void main(String[] args) { for (int day = 0; day < 3; day++) { Emperor emperor = Emperor.getInstance(); emperor.say(); }//三天见的皇帝都是同一个人, 荣幸吧! } }
有多个实例的单例
/** * 皇帝类 */ public class Emperor2 { //定义最多能产生的实例数量 private static int maxNumOfEmperor = 2; //每个皇帝都有名字, 使用一个ArrayList来容纳, 每个对象的私有属性 private static ArrayList<String> nameList=new ArrayList<String>(); //定义一个列表, 容纳所有的皇帝实例 private static ArrayList<Emperor2> emperorList=new ArrayList<Emperor2>(); //当前皇帝序列号 private static int countNumOfEmperor =0; //产生所有的对象 static{ for(int i=0;i<maxNumOfEmperor;i++){ emperorList.add(new Emperor2("皇"+(i+1)+"帝")); } } private Emperor2(){ //世俗和道德约束你, 目的就是不产生第二个皇帝 } //传入皇帝名称, 建立一个皇帝对象 private Emperor2(String name){ nameList.add(name); } //随机获得一个皇帝对象 public static Emperor2 getInstance(){ Random random = new Random(); //随机拉出一个皇帝, 只要是个精神领袖就成 countNumOfEmperor = random.nextInt(maxNumOfEmperor); return emperorList.get(countNumOfEmperor); } //皇帝发话了 public static void say(){ System.out.println(nameList.get(countNumOfEmperor)); } }
/** * 臣子类 */ public class Minister2 { public static void main(String[] args) { //定义5个大臣 int ministerNum =5; for(int i=0;i<ministerNum;i++){ Emperor2 emperor = Emperor2.getInstance(); System.out.print("第"+(i+1)+"个大臣参拜的是: "); emperor.say(); } } }
3、优点:在内存中只有一个实例,减少内存开支,特别是一个对象需要频繁地创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显。
4、使用场景:
要求生成唯一序列号的环境;
在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;
创建一个对象需要消耗的资源过多, 如要访问IO和数据库等资源;
需要定义大量的静态常量和静态方法( 如工具类)的环境,可以采用单例模式(当然,也可以直接声明为static的方式)。