设计模式(一)--单例模式的java实现

         23中设计模式中,单例模式是我接触最多的模式,也是我目前为止唯一真正自己编程的时候用到的设计模式。。。。

         单例模式的思想:在工程存续阶段,这个类只能有一个对象存在在内存里。常见的工具类,资源连接类等很多都是单例的。spring框架中的bean,默认情况下也是单例的(节省资源,提高效率)。

        写法1:

     

package InvolvedMode.single;

/**  
 *  Single : 
 * @author xuejupo  [email protected] 
 * create in 2015-12-17 下午8:09:48    
 */

public class Single {
	public static void main(String[] args){
		//访问类:
		try {
			ClassLoader.getSystemClassLoader().loadClass("InvolvedMode.single.single1");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("类加载完成----------");
		int i = single1.i;
		System.out.println("访问类中的成员------");
		single1 s = single1.getSingle();
		s.myMeoth();
	}
}
class single1{
	public static int i = 1;
	public int getI(){
		return i;
	}
	static{
		System.out.println("变量被加载");
	}
	private single1(){
		System.out.println("类被初始化");
	}
	private static single1 single = new single1();
	public static single1 getSingle(){
		return single;
	}
	public void myMeoth(){
	}
}

 结果:

类加载完成----------
变量被加载
类被初始化
访问类中的成员------

 写法2:

public class Single {
	public static void main(String[] args){
		//访问类:
		try {
			ClassLoader.getSystemClassLoader().loadClass("InvolvedMode.single.single2");
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("类加载完成----------");
		int i = single2.i;
		System.out.println("访问类中的成员------");
		single2 s = single2.getSingle();
		s.myMeoth();
	}
}
class single2{
	public static int i = 1;
	static{
		System.out.println("变量被加载");
	}
	private single2(){
		System.out.println("类被初始化");
	}
	private static class Singleton{
		static{
			System.out.println("内部类被加载");
		}
		private static final single2 INSTANCE = new single2();
	}
	public static single2 getSingle(){
		return Singleton.INSTANCE;
	}
	public void myMeoth(){
	}
}

 结果:

类加载完成----------
变量被加载
访问类中的成员------
内部类被加载
类被初始化

 写法3:

enum single3{
	SINGLE;
	private single3(){
		System.out.println("类被初始化");
	}
	static{
		System.out.println("变量被加载");
	}
	static int i;
	public void myMethod(){
	}
}

 类似的,方法3就不贴测试用例了,结果为:

类加载完成----------
类被初始化
变量被加载
访问类中的成员------

       总结:

       从以上结果可以看到,真正延迟加载的只是写法2:只有在用到单例模式的时候,整个类才会被初始化。写法一和写法3中,类被加载的时候不会初始化整个类,但是如果访问类的属性,就会初始化整个类(调用类的构造函数,实际上这时候类并不需要被构造,所以不是延迟加载)(网上很多人说的类被加载的时候就会初始化整个类肯定是不对的,但是除了类中变量被访问,不知道还有没有别的方法使整个类被初始化,比如用反射机制,还有一些容器的特殊的加载---加载类的时候也加载类的静态成员变量,这个有待考究)。

       写法3是用枚举实现单例模式,这种写法很新颖,是1.5版本后出现的写法,Effective Java这本书推荐写法,这种写法可以使单例模式避免利用反射机制的攻击,真正实现了绝对只有一个实例的思想。

猜你喜欢

转载自709002341.iteye.com/blog/2264886