欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

单例模式的几种实现方式

程序员文章站 2022-06-27 23:33:43
1)饿汉式 public class Person{ // 私有的构造方法 private Person{} /* private Person person = new Person(); 出现*Error错误 因为创建对象需要调用构造方法执行 构造方法执行在栈内存中 每次创建对象需要加载属性 该属性又是当前类对象 造成无限循环创建对象 最终栈内存压满 不释放...

1)饿汉式

    public class Person{
        // 私有的构造方法
        private Person{}
        /* private Person person = new Person();
          出现*Error错误 因为创建对象需要调用构造方法执行
          构造方法执行在栈内存中 每次创建对象需要加载属性 该属性又是当前类对象 
         造成无限循环创建对象 最终栈内存压满 不释放
         栈内存的空间比堆内存要小 所以栈内存先堆满 
         因此需要加static修饰符 static修饰的元素属于类 只加载一次
       */       
         //final 修饰的属性基本类型是值不能改变 引用类型是地址不能改变 防止用户拿到对象 将对象置为null                
         //私有的当前类对象作为属性
        private static final Person person = new Person();
        // 公有的方法 用来获取该类对象
        /*
        static 调该方法的两种方式 
        1)类名点(方法需要static修饰)  
        2)对象点(该方法用来获取当前类对象 此时还没有对象)
        */
        public static Person getPerson(){
            return person;
        }

    }

2)双重if检测模型

    public class Person{
        // 私有构造方法
        private Person{}
        /*
         valatile 修饰属性 有以下几个特点:
          1. 属性在某一个线程操作的时候 属性是锁定的 其他的线程没法获取属性
          2. 属性被某一个线程修改后 另外的线程立即可见
          3. 可以禁止指令重新排布
        当被volatile修饰后 堆必须先分配一个对象内存 必须再将对象内存的地址交给栈引用 最后往对象空间中摆放东西
        没有volatile修饰时 可能会产生摆放东西时又来了一个对象 而此时并没有将地址引用交给栈
        */
        private static volatile Person person;
        // 公有静态方法 获取该类对象
        public static Person getPerson(){
            if(person == null){
                // 锁定当前类
                synchronized (Person.class){
                    // 锁定时多线程并发 两个线程经过第一次判断都为null 当一个线程要锁还没锁的时候 另一个线程却锁住了 new出了对象 
                    // 而此时没锁住的那个线程这个时候再锁 此时对象已经有了 所以需要再进行一次判断
                    if(person == null){
                        person = new Person();
                    }
                }
            }
            return person;
        }
    }

3)枚举实现单例

*序列化、线程安全(枚举本身是线程安全的)

    public enum Person{
        PERSONONE;
        public Person getInstance(){
            return Person.PERSONONE;
        }
    }

4)static代码块实现单例模式

    public class Person {
        private Person(){}
        private static final Person PERSON;
        static {
            PERSON = new Person();
        }
        public static Person getInstance(){
            return PERSON;
        }
    }

5)静态内部类实现

    public class Person {

        private Person(){}

        private static class Holder{
            private static final Person person = new Person();
        }
        public static Person getInstance(){
            return Holder.person;
        }
    }

拓展

静态内部类加载顺序问题

    public class Test {

            public static void main(String[] args) {             
                new A.C(); 
                //内部类静态属性p2   内部类静态块   内部类属性p1    内部类属性p3  内部类普通块 内部类构造
            }
    }

    class A {
        private P p1 = new P("A类属性p1");
        static P p3 = new P("A类静态属性p2");

        public A() {
            System.out.println("A类构造方法");
        }

        private P p2 = new P("A类属性p3");

        static {
            System.out.println("A类静态块");
        }

        {
            System.out.println("A类普通块");
        }

        public static class C {
            private P p1 = new P("内部类属性p1");
            static P p2 = new P("内部类静态属性p2");

            public C() {
                System.out.println("内部类构造");
            }

            private P p3 = new P("内部类属性p3");

            static {
                new P("内部类静态块");
            }

            {
                new P("内部类普通块");
            }
        }
    }
    class P {
        public P(String s) {
            System.out.println(s);
        }

    }

本文地址:https://blog.csdn.net/weixin_45555680/article/details/111877074

相关标签: 设计模式