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

    设计 模式被分为23种

    包括:

    创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
    结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
    行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
     
    这里说明单例模式
    单例模式:
    Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)
     
    个人理解:创建一个独用的全局变量,想要只实例化一次,且可以获取到
     
    推荐参考:这里
     
    原作者表述很清晰,我就不再总结了
    以下是原文粘贴

    1、饿汉式(静态常量)[可用]

    复制代码
    public class Singleton {
    
        private final static Singleton INSTANCE = new Singleton();
    
        private Singleton(){}
    
        public static Singleton getInstance(){
            return INSTANCE;
        }
    }
    复制代码

    优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。

    缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。

    2、饿汉式(静态代码块)[可用]

    复制代码
    public class Singleton {
    
        private static Singleton instance;
    
        static {
            instance = new Singleton();
        }
    
        private Singleton() {}
    
        public Singleton getInstance() {
            return instance;
        }
    }
    复制代码

    这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候,就执行静态代码块中的代码,初始化类的实例。优缺点和上面是一样的。

    3、懒汉式(线程不安全)[不可用]

    复制代码
    public class Singleton {
    
        private static Singleton singleton;
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (singleton == null) {
                singleton = new Singleton();
            }
            return singleton;
        }
    }
    复制代码

    这种写法起到了Lazy Loading的效果,但是只能在单线程下使用。如果在多线程下,一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以在多线程环境下不可使用这种方式。

    4、懒汉式(线程安全,同步方法)[不推荐用]

    复制代码
    public class Singleton {
    
        private static Singleton singleton;
    
        private Singleton() {}
    
        public static synchronized Singleton getInstance() {
            if (singleton == null) {
                singleton = new Singleton();
            }
            return singleton;
        }
    }
    复制代码

    解决上面第三种实现方式的线程不安全问题,做个线程同步就可以了,于是就对getInstance()方法进行了线程同步。

    缺点:效率太低了,每个线程在想获得类的实例时候,执行getInstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。方法进行同步效率太低要改进。

    5、懒汉式(线程安全,同步代码块)[不可用]

    复制代码
    public class Singleton {
    
        private static Singleton singleton;
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (singleton == null) {
                synchronized (Singleton.class) {
                    singleton = new Singleton();
                }
            }
            return singleton;
        }
    }
    复制代码

    由于第四种实现方式同步效率太低,所以摒弃同步方法,改为同步产生实例化的的代码块。但是这种同步并不能起到线程同步的作用。跟第3种实现方式遇到的情形一致,假如一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。

    6、双重检查[推荐用]

    复制代码
    public class Singleton {
    
        private static volatile Singleton singleton;
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (singleton == null) {
                synchronized (Singleton.class) {
                    if (singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    复制代码

    Double-Check概念对于多线程开发者来说不会陌生,如代码中所示,我们进行了两次if (singleton == null)检查,这样就可以保证线程安全了。这样,实例化代码只用执行一次,后面再次访问时,判断if (singleton == null),直接return实例化对象。

    优点:线程安全;延迟加载;效率较高。

    7、静态内部类[推荐用]

    复制代码
    public class Singleton {
    
        private Singleton() {}
    
        private static class SingletonInstance {
            private static final Singleton INSTANCE = new Singleton();
        }
    
        public static Singleton getInstance() {
            return SingletonInstance.INSTANCE;
        }
    }
    复制代码

    这种方式跟饿汉式方式采用的机制类似,但又有不同。两者都是采用了类装载的机制来保证初始化实例时只有一个线程。不同的地方在饿汉式方式是只要Singleton类被装载就会实例化,没有Lazy-Loading的作用,而静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getInstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。

    类的静态属性只会在第一次加载类的时候初始化,所以在这里,JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。

    优点:避免了线程不安全,延迟加载,效率高。

    8、枚举[推荐用]

    public enum Singleton {
        INSTANCE;
        public void whateverMethod() {
    
        }
    }

    借助JDK1.5中添加的枚举来实现单例模式。不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。可能是因为枚举在JDK1.5中才添加,所以在实际项目开发中,很少见人这么写过。

    优点

    系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。

    缺点

    当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new,可能会给其他开发人员造成困扰,特别是看不到源码的时候。

    适用场合

    • 需要频繁的进行创建和销毁的对象;
    • 创建对象时耗时过多或耗费资源过多,但又经常用到的对象;
    • 工具类对象;
    • 频繁访问数据库或文件的对象。
  • 相关阅读:
    android29
    android28
    android27
    android26
    Dynamics CRM2011 MspInstallAction failed when installing an Update Rollup
    Dynamics CRM Import Solution Attribute Display Name description is null or empty
    The service cannot be activated because it does not support ASP.NET compatibility
    IIS部署WCF报 无法读取配置节“protocolMapping”,因为它缺少节声明
    Unable to access the IIS metabase.You do not have sufficient privilege
    LM算法与非线性最小二乘问题
  • 原文地址:https://www.cnblogs.com/yishilin/p/8427279.html
Copyright © 2011-2022 走看看