zoukankan      html  css  js  c++  java
  • 设计模式(单例模式)

    一、简介

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

    二、使用场景及优点

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



  • 相关阅读:
    centos7.0 没有netstat 命令问题
    Linux系统下安装rz/sz命令及使用说明
    怎样查看linux版本
    MongoDB 的 GridFS 详细分析
    MongoDb的bin目录下文件mongod,mongo,mongostat命令的说明及使用
    MongoDB基本使用
    安装concrete时提示“...database does not support InnoDB database tables..."如何解决
    最近开始研究PMD(一款采用BSD协议发布的Java程序代码检查工具)
    如何利用论坛做推广 | 一个每天可以吸引50粉丝的推广思路
    那些高阅读量文章的标题都是怎么取的?14种模板直接套用
  • 原文地址:https://www.cnblogs.com/pocter/p/3684458.html
Copyright © 2011-2022 走看看