在java中,单例设计模式是非常常见的设计模式,对单例设计模式的概念,不做过多的介绍,下面将逐一介绍四种单例设计模式:
1、第一种单例设计模式
1.1 代码实现
package com.singleton.one; /** * 第一种单例设计模式 * @author Administrator * */ public class SingleTonOne { // 实例化 private static SingleTonOne instance = new SingleTonOne(); // 私有构造方法 private SingleTonOne(){ System.out.println("---singleton one---"); } // 获取单例实例 public static SingleTonOne getInstance(){ return instance; } // 静态方法 public static void hello(){ System.out.println("---singleton one hello---"); } }
1.2 相关测试
package com.singleton.test; import static org.junit.Assert.assertTrue; import org.junit.Test; import com.singleton.one.SingleTonOne; public class TestSingleTonOne { /** * 测试是否是单例 */ @Test public void testSingleTonOne(){ SingleTonOne one1 = SingleTonOne.getInstance(); SingleTonOne one2 = SingleTonOne.getInstance(); assertTrue(one1 == one2); } /** * 测试第一种单例的加载方式 * 运行结果: * ---singleton one--- * ---singleton one hello--- * 1、先执行了私有构造方法; * 2、然后再执行静态方法 * 结论: * 当单纯的调用静态方法时,调用了私有构造方式是没有必要,也就是 * 无法实现懒加载 */ @Test public void testSingleTonOneLoad(){ SingleTonOne.hello(); } }
2、第二种单例
2.1 代码实现
package com.singleton.one; /** * 第二种单例设计模式 * @author Administrator * */ public class SingleTonTwo { private static SingleTonTwo instance ; private SingleTonTwo(){ System.out.println("-- singleton two --"); } /** * 懒加载处理,但是线程不安全 * @return */ // public static SingleTonTwo getInstance(){ // if (instance == null){ // instance = new SingleTonTwo(); // } // // return instance; // } /** * 上述注释的getInstance是非线程安全的,该方法做了同步处理; * 但是由于线程处理,往往效率不高 */ public static synchronized SingleTonTwo getInstance(){ if (instance == null){ instance = new SingleTonTwo(); } return instance; } public static void hello(){ System.out.println("-- single ton two hello --"); } }
2.2 相关测试
package com.singleton.test; import static org.junit.Assert.assertTrue; import org.junit.Test; import com.singleton.one.SingleTonTwo; /** * 测试四种单例方式 -- 第二种单例(懒加载) * @author Administrator * */ public class TestSingleTonTwo { /** * 测试是否是单例 */ @Test public void testSingleTonTwo(){ SingleTonTwo one1 = SingleTonTwo.getInstance(); SingleTonTwo one2 = SingleTonTwo.getInstance(); assertTrue(one1 == one2); } /** * 测试第二种单例测试 * 运行结果: * -- single ton two hello -- * 结论: * 运行静态方法时,不会调用私有构造方法(即:懒加载) */ @Test public void testSingleTonTwoLoad(){ SingleTonTwo.hello(); } }
3、内部类实现单例
3.1 代码实现
package com.singleton.one; /** * 内部类实现单例 */ public class SingleTonThree { private SingleTonThree(){ System.out.println("-- SingleTon Three --"); } /** * 内部类实例化 * @author Administrator * */ private static class SingleTonThreeHandler{ public static SingleTonThree instance = new SingleTonThree(); } /** * 通过内部类,获取实例 * @return */ public static SingleTonThree getInstance(){ return SingleTonThreeHandler.instance; } public static void hello(){ System.out.println("-- SingleTonThree hello --"); } }
3.2 相关测试
package com.singleton.test; import static org.junit.Assert.assertTrue; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.junit.Test; import com.singleton.one.SingleTonThree; /** * 测试四种单例方式 -- 第三种单例(内部静态类) * @author Administrator * */ public class TestSingleTonThree { /** * 测试是否是单例 */ @Test public void testSingleTonThree(){ SingleTonThree one1 = SingleTonThree.getInstance(); SingleTonThree one2 = SingleTonThree.getInstance(); assertTrue(one1 == one2); } /** * 第三种单例测试 * 运行结果: * -- SingleTonThree hello -- * 结论: * 没有触发构造方法,仅仅执行了方法内部逻辑;实现了懒加载方式。 */ @Test public void testSingleTonThreeLoad(){ SingleTonThree.hello(); } }
4、枚举实现单例
4.1 代码实现
package com.singleton.one; /** * 枚举类型实现单例 * @author Administrator * */ public enum SingleTonEnum { /** * 单例实例 */ INSTANCE; private SingleTonEnum(){ System.out.println("-- enum singleton --"); } public static void hello(){ System.out.println("-- eum singleton hello --"); } }
4.2 相关测试
package com.singleton.test; import org.junit.Test; import static org.junit.Assert.*; import com.singleton.one.SingleTonEnum; /** * 测试枚举类型单例 * @author Administrator * */ public class TestSingleTonEnum { /** * 测试是否是单例 */ @Test public void testSingleTonEnum(){ SingleTonEnum enum1 = SingleTonEnum.INSTANCE; SingleTonEnum enum2 = SingleTonEnum.INSTANCE; assertTrue(enum1 == enum2); } /** * 测试是否懒加载 * 结果: * -- enum singleton -- * -- eum singleton hello -- * 该枚举类型,无法懒加载 */ @Test public void testSingleTonEnum1(){ SingleTonEnum.hello(); } }
5、四种单例效率测试
package com.singleton.test; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.singleton.one.SingleTonEnum; import com.singleton.one.SingleTonOne; import com.singleton.one.SingleTonThree; import com.singleton.one.SingleTonTwo; /** * 测试四种单例的效率 * 运行结果: * ---singleton one--- * 3 * -- singleton two -- * 57 * -- SingleTon Three -- * 4 * -- enum singleton -- * 3 * 结果分析: * 第二种时间消耗最多,由于其同步处理了,而导致更多的开销 * @author Administrator * */ public class TestSingleTon { long start; long end; @Before public void setUp(){ start = System.currentTimeMillis(); } @Test public void testSingleTonOne(){ for (int i = 0; i < 1000000; i++){ SingleTonOne instance = SingleTonOne.getInstance(); } } @Test public void testSingleTonTwo(){ for (int i = 0; i < 1000000; i++){ SingleTonTwo instance = SingleTonTwo.getInstance(); } } @Test public void testSingleTonThree(){ for (int i = 0; i < 1000000; i++){ SingleTonThree instance = SingleTonThree.getInstance(); } } @Test public void testSingleTonEnum(){ for (int i = 0; i < 1000000; i++){ SingleTonEnum enum1 = SingleTonEnum.INSTANCE; } } @After public void tearDown(){ end = System.currentTimeMillis(); System.out.println(end - start); } }
6、总结
第一种单例:不具备懒加载的功效;
第二种单例:懒加载、如果分为线程安全和非线程安全两种,当使用线程安全同步时,会影响效率。
第三种单例:懒加载、且适合多线程,效率很高;但是可以通过java反射来实例化多个实例,因此在一般情况下,该方式实现比较好;
第四种单例:必须在jdk5.0以上才具备的,未实现懒加载,多线程友好,并且无法通过java反射来实例化多个实例。
在一般情况下,建议使用第三种和第四种方式。
java中的四种单例实现方式
时间: 2024-10-04 20:01:21