• 设计模式之单例模式——Singleton


                   

                        设计模式之单例模式——Singleton

    设计意图:

     保证类仅有一个实例,并且可以供应用程序全局使用。为了保证这一点,就需要这个类自己创建自己的对象,并且对外有公开的调用方法而且,别的类不能实例化它,所以构造方法要设置为私有的。

    单例模式的要点   

    一是某个类只能有一个实例;

    二是它必须自行创建这个实例;

    三是它必须自行向整个系统提供这个实例。

    例如:

    有一个"单例对象",而"客户甲""客户乙" "客户丙"是单例对象的三个客户对象。可以看到,所有的客户对象共享一个单例对象。而且从单例对象到自身的连接线可以看出,单例对象持有对自己的引用。一些资源管理器常常设计成单例模式。在计算机系统中,需要管理的资源包括软件外部资源,譬如每台计算机可以有若干个打印机,但只能有一个Printer Spooler, 以避免两个打印作业同时输出到打印机中。每台计算机可以有若干传真卡,但是只应该有一个软件负责管理传真卡,以避免出现两份传真作业同时传到传真卡中的情况。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。

    实现的方法:

    单例模式有很多种,下面就来介绍一下单例模式的几种使用方法吧:
    【饿汉模式】饿汉法就是在第一次引用该类的时候就创建对象实例,而不管实际是否需要创建。

    public   class   Singleton{
        private static final Singleton singleton = new Singleton();
        /**
         * 私有构造函数
         */
        private   Singleton(){
            
        }
        /**
         * 获得实例
         * @return
         */
        public static Singleton getInstance(){
            return singleton;
        }
        public static void say(){
            System.out.println("单例模式创建啦!");
            
        }
    }
    public class main {
        public static void main(String[] args) {
            main m=new main();
            Singleton.getInstance().say();
        }
    
    }

    这样做的好处是编写简单,但是无法做到延迟创建对象。但是我们很多时候都希望对象可以尽可能地延迟加载,从而减小负载,所以就需要下面的懒汉法:

     【懒汉法】

     这种方法可以实现延时加载,但是有一个致命弱点:线程不安全。如果有两条线程同时调用getSingleton()方法,就有很大可能导致重复创建对象。

    public class Singleton {
        private static Singleton singleton = null;
        private Singleton(){}
        public static Singleton getSingleton() {
            if(singleton == null) singleton = new Singleton();
            return singleton;
        }
    }

    解决线程不安全的三种方法:

    1、在getInstance方法上加同步

     

    public static synchronized Singleton getInstance() {  
             if (single == null) {    
                 single = new Singleton();  
             }    
            return single;  
    } 
     

    2、双重检查锁定

    synchronized (Singleton.class),相当于在Singleton对象上加了锁,任何一个线程如果的到了这把锁就可以先运行,直到到他执行完其他线程才有可能得到这把锁,再进入执行。
    public static Singleton getInstance() {  
            if (singleton == null) {    
                synchronized (Singleton.class) {    
                   if (singleton == null) {    
                      singleton = new Singleton();   
                   }    
                }    
            }    
            return singleton;   
        }  
     

    3、静态内部类

     

    public class Singleton {    
        private static class LazyHolder {    
           private static final Singleton INSTANCE = new Singleton();    
        }    
        private Singleton (){}    
        public static final Singleton getInstance() {    
           return LazyHolder.INSTANCE;    
        }    
    }    

    思考:java中单例模式和静态类(一个类,所有方法为静态方法)的区别

    由于单例模式和静态类都具有良好的访问性,它们之间有许多相似之处,例如,两者可以直接使用而无须创建对象,都可提交唯一实例,在一个非常高的高度上看起来它们都为是用于同样的任务。

    1.那么在java中什么时候该使用单例模式,什么时候该使用静态类呢?

           如果你的单例不需要维护任何状态,仅仅提供全局访问的方法,这种情况考虑使用静态类,静态方法比单例更快,因为静态的绑定是在编译期就进行的。但是要记住,不建议在静态类中维护状态信息,特别是在并发环境中,若无适当的同步措施而修改多线程并发时,会导致坏的竞态条件。
          如果你需要将一些工具方法集中在一起时,你可以选择使用静态方法,但是别的东西,要求单例访问资源时,应该使用单例模式。
     
    2.Java中单例(变现类)与静态类(表现方法)的区别
    1)静态类比单例具有更好的性能,因为静态方法在编译期绑定。
    2)再次,它们的区别是override的能力,因Java中的静态方法是不可以覆盖的,这就导致其木有太多的灵活性,另一面,你可通过继承的方式覆盖单例类中定义的方法。
    3)静态类很难模拟,因此难于单例测试,单例更容易模拟,因为也比静态类易于编写单元测试,不论神马单例期望神马,你都可以传递模拟对象,例如构造方法或方法参数。
    4)如果你的需求中需要维护状态信息,则单例比静态类更适合,因为后者在维护状态信息方面是非常可怕的,并导致狡滑的bug。
    5)如果是一个非常重的对象,单例可以懒加载,但是静态类没有这样的优势,并且非常热切的加载。
    6)许多依赖注入的框架对单例都有良好的管理,例如Spring,使用它们非常容易。
     
     
    3.Java中,选择单例而不是静态类的优点
    单例与静态主要的优点是前者比后者更具有面向对象的能力,使用单例,可以通过继承和多态扩展基类,实现接口和更有能力提供不同的实现,如果我们讨论java.lang.Runtime,在Java中它是单例,调用getRuntime()方法,会基于不同的JVM返回不同的实现,但也保证了每个JVM中实有一个实例,如果java.lang.Runtime是一个静态类,不太可能因不同的JVM返回不同的实现。
     
    这就是Java中单例与静态类的区别,当你需要一个全能力的对象时,选择单例,如果仅仅是将一些静态方法预售,使用静态类。
     
  • 相关阅读:
    Java导出Excel(附完整源码)
    Scala语言学习笔记——方法、函数及异常
    python时间序列按频率生成日期
    socket主要函数介绍
    JAVA版CORBA程序
    Linux文件压缩命令笔记
    使用JAVA写一个简单的日历
    Node.js 文件系统
    Node.js 常用工具util
    Node.js 全局对象
  • 原文地址:https://www.cnblogs.com/java-7/p/6053540.html
Copyright © 2020-2023  润新知