美文网首页程序员想法
设计模式之单例模式,每个人都是唯一

设计模式之单例模式,每个人都是唯一

作者: java程序员思维 | 来源:发表于2019-04-30 09:05 被阅读2次

    单例模式

    单例模式(SingletonPattern)是 Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

    单例模式解决的问题

    保证一个类仅有一个实例,并提供一个访问它的全局访问点。防止一个全局使用的类频繁地创建与销毁,节省资源,方便管理。

    单例模式注意事项

    单例类只能有一个实例。单例类必须自己创建自己的唯一实例,其他任何地方无法通过构造方法创建对象,也意味着需要构造方法私有化。单例类必须给所有其他对象提供这一实例。

    使用场景

    网站的计数器,一般也是采用单例模式实现,否则难以同步。

    数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。

    操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。

    代码实现

    单例模式又分为懒汉模式和饿汉模式,两种的区别在于是不是启动的时候创建对象,饿汉模式不管是否需要对象,都先创建好。懒汉模式是在需要对象的时候,进行对象的创建。本质区别是时间和空间的取舍,懒汉模式是用时间换空间,启动时候不需要创建对象,节省了空间,但是访问对象的时候要判断是否已经创建对象,会浪费一些时间。饿汉模式是用空间换时间,启动的时候创建对象,浪费了一些空间,但是访问的时候,不需要创建对象和判断对象是否存在,节省了时间,提高了效率。

    //懒汉模式

    public class Singleton {

        private Singleton() {

        }

        private static Singleton instance = null;

        /* 静态工程方法,创建实例  缺点非线程安全*/

        public static Singleton getInstance() {

            if (instance == null) {

                instance = new Singleton();

            }

            return instance;

        }

    }

    public class SingletonHungry {

        //构造器私有化

        private SingletonHungry(){}

        private static SingletonHungry instance = new SingletonHungry();

        /* 静态工程方法,创建实例*/

        public static SingletonHungry getInstance() {

            return instance;

        }

    }

    上面的懒汉模式存在一些问题,在多线程的情况下,多个线程同时调用getInstance方法,可能会创建多个对象,违背了单例模式只有一个实例的原则,需要对getInstance进行同步处理。

    public class Singleton {

        private Singleton() {

        }

        private static Singleton instance = null;

        public static synchronized Singleton getInstance() {

            if (instance == null) {

                instance = new Singleton();

            }

            return instance;

        }

    }

    虽然上面的代码可以保证只会创建一个单例,但是效率很低,是对整个getInstance方法加锁,一旦对象已经创建,每次只能有一个线程访问对象,可以通过双检锁的方式进行优化,既可以保证只会创建一个对象,同时又允许多个线程访问实例。

    public class Singleton {

        private Singleton() {

        }

        private volatile static Singleton instance = null;

        public static Singleton getInstance() {

            if (instance == null) {

                synchronized (instance) {

                    if (instance == null) {

                        instance = new Singleton();

                    }

                }

            }

            return instance;

        }

    }

    使用volatile修饰instance属性,保证属性的可见性,只要发生变化对所有线程可见,因为同步代码范围变小,可以提高效率。双检锁可以保证只会创建一个对象实例。

    保证单例,还有很多方式,枚举自身是线程安全的,也是一种不错的选择。

    public enum Signleton {

        INSTANCE;

        private Something something;

        Signleton() {

            something = new Something();

        }

        public Something getSomething() {

            return something;

        }

    }

    优缺点

    优点:在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。由于在系统内存中只存在一个对象,因此可以 节约系统资源,当需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。 

    缺点:不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。 单例类的职责过重,在一定程度上违背了“单一职责原则”。 

    我的启发

    世界上没有两片完全相同的树叶,人何尝不是如此,每个人都是唯一,做最真实的自我。我是幸运的,因为我还活着,珍爱生命,过好每一天。

    相关文章

      网友评论

        本文标题:设计模式之单例模式,每个人都是唯一

        本文链接:https://www.haomeiwen.com/subject/ddfmnqtx.html