• 设计模式(单例模式)


    一、简介

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

    二、使用场景及优点

    对于频繁使用的对象,可以省略创建对象花费的时间。同时由于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();
            }
        }
    }



  • 相关阅读:
    vue自定义指令使用注意事项
    es6新增方法---实用
    webpack和gulp的区别
    OSI 5层协议,socket,从协议角度看网络通信
    网络通信流程
    数据相关的模块
    一些模块
    面向对象
    ATM作业
    XML模块增删改查基本操作
  • 原文地址:https://www.cnblogs.com/pocter/p/3684458.html
Copyright © 2020-2023  润新知