设计模式(单例模式)

一、简介

单例模式是设计模式中使用最普遍的一种设计模式,它是对象创建模式,用于产生一个对象的具体实例,
 确保系统中一个类只有一个实例。

二、使用场景及优点

对于频繁使用的对象,可以省略创建对象花费的时间。同时由于new操作的吃书减少,因此对系统内存
的使用频率会降低,减轻了GC压力,缩短了GC停顿时间。

三、常见表现形式

1.在类加载时初始化单例属性(优点:效率较高,多线程安全;缺点:增多程序加载时的额外负载)

public class ServiceConnation1
{
    /**
     * 类加载时就实例化单例属性,此策略较为安全,多线程时不会产生多个实例。但是当被实例化的
     * 类的构造方法需要做大量工作、或做者远程连接操作就会使得程序在启动时耗去很长的时间,致
     * 使启动时间延长,用户体验降低。
     */
    private static ServiceConnation1 sc = new ServiceConnation1();
    
    private InitialContext context;
    
    private ServiceConnation1()
    {
        try
        {
            /**
             * 此处并没有指定properties属性,只是示例简要的结构,模拟远程连接操作等
             * 较为耗时的初始化代码,程序并不能运行成功。
             */
            context = new InitialContext();
        }
        catch (NamingException e)
        {
            e.printStackTrace();
        }
    }
    
    public static ServiceConnation1 getInstance()
    {
        return sc;
    }
    
    public Object getService(String name) throws NamingException
    {
        
        return context.lookup(name);
    }
}

2.延迟加载策略(优点:减少程序加载时的负载;缺点:需要引入同步,效率低下)

 

public class ServiceConnation2
{
    
    private static ServiceConnation2 sc = null;
    
    private InitialContext context;
    
    private ServiceConnation2()
    {
        try
        {
            /**
             * 此处并没有指定properties属性,只是示例简要的结构,模拟远程连接操作等
             * 较为耗时的初始化代码,程序并不能运行成功。
             */
            context = new InitialContext();
        }
        catch (NamingException e)
        {
            e.printStackTrace();
        }
    }
    
    public static synchronized ServiceConnation2 getInstance()
    {
        /**
         * 在调用方法是判断是否初始化单例对象,这样可以很好的解决上述启动耗时的问题,方法在不添
         * 加同步关键字的时候,在非多线程运行下较为可靠,效率也较高。但是在多线程的情况下可能会
         * 产生多个实例,因此需要给方法添加synchronized修饰,这样效率也大大降低了。
         */
        if(sc == null){
            sc = new ServiceConnation2();
        }
        return sc;
    }
    
    public Object getService(String name) throws NamingException
    {
        
        return context.lookup(name);
    }
}

3.内部类延迟加载策略(改进前两种的缺点,推荐使用)

public class ServiceConnation3
{
    
    private InitialContext context;
    
    private ServiceConnation3()
    {
        try
        {
            /**
             * 此处并没有指定properties属性,只是示例简要的结构,模拟远程连接操作等
             * 较为耗时的初始化代码,程序并不能运行成功。
             */
            context = new InitialContext();
        }
        catch (NamingException e)
        {
            e.printStackTrace();
        }
    }
    
    public static ServiceConnation3 getInstance()
    {
        /**
         * 为了解决因延长加载而带来的同步效率低下的问题,将程序改进为内部类的方式实例化单例对象
         */
        return ServiceConnationHolder.sc;
    }
    
    public Object getService(String name) throws NamingException
    {
        return context.lookup(name);
    }
    
    /**
     * ServiceConnationHolder为内部类,在程序初始化的收不会被加载,因此利用内部类的
     * 这种特性可以实现延迟加载,同时又不存在多线程安全带的问题。
     */
    private static class ServiceConnationHolder
    {
        private static ServiceConnation3 sc = new ServiceConnation3();
    }
}

 

四、测试

public class ServiceConnation
{
    
    private ServiceConnation()
    {
        try
        {
            System.out.println("************do inital something************");
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
    
    public static ServiceConnation getInstance()
    {
        return ServiceConnationHolder.instance;
    }
    
    public Object getService(String name) throws NamingException
    {
        System.out.println("************getService************");
        return new Object();
    }
    
    private static class ServiceConnationHolder{
        public static ServiceConnation instance = new ServiceConnation();
    }
}

 

public class SingletonTest
{
    @Test
    public void testInitalSingleton(){
        ServiceConnation sc = ServiceConnation.getInstance();
        try
        {
            sc.getService("beanName1");
            sc = ServiceConnation.getInstance();
            sc.getService("beanName2");
        }
        catch (NamingException e)
        {
            e.printStackTrace();
        }
    }
}



 

 

 

posted @ 2013-11-18 19:15  Pocter  阅读(167)  评论(0编辑  收藏  举报