• 设计模式(一)单例模式


    1.单例模式【Singleton  Pattern】:

    设计模式:对问题行之有效的解决方式。其实它是一种思想,当人们在写代码的过程中,发现有些代码可提高效率,或者可复用,或者更灵活,在不断的实践中,提取出的一些代码,根据特点命名,就出现了设计模式。

    1,单例设计模式。
        解决的问题:就是可以保证一个类在内存中的对象唯一性。

    UMl单例图:

    饿汉式:这个类被加载的时候,静态变量会被初始化,类的对象就存在了。一加载,就创建这个唯一的对象。

        class EagerSingle {
        /**
         * 饿汉式
         * 这个类被加载的时候,静态变量会被初始化,类的对象就存在了
         */
        private static  final EagerSingle s = new EagerSingle();
        /**
         * 私有的默认的构造方法,避免外界通过构造方法new多个实例,
         * 构造方法是私有的,此类不能被继承
         */
        private EagerSingle(){
            
        }
        /**
         * 静态工厂方法
         * @return
         */
        public static synchronized  EagerSingle getInstance(){
            return s;
        }
        
        
    }

    懒汉式:类加载的时候,没有对象,只有调用getInstace()方法,对象才会被创建

    class LazySingle{
            private static  LazySingle s1 = null;
            //私有的构造方法
            private LazySingle(){
                
            }
            /**
             * 加synchronized:
             * 原因:
             * 多个线程并发操作共享数据s1,因为有多条语句操作共享数据,会出现线程安全问题。
             * 可能创建多个对象,存在线程安全的问题,则用同步锁,
             * 在方法上加同步锁,或者加同步代码块,该类所属的类字节码锁
             * @return
             */
            public static synchronized LazySingle getInstance(){
                synchronized (LazySingle.class) {
                    if(s1 != null){
                        //--A
                        //--B
                        //new 了不只一个对象
                        s1 = new LazySingle();
                    }
                }
                
                return s1;
            }
        }
    public class Single{
            public static void main(String[] args) {
                // TODO Auto-generated method stub
                LazySingle ls1 = LazySingle.getInstance();
                LazySingle ls2 = LazySingle.getInstance();
                System.out.println(ls1==ls2);        }
        }

    输出结果为:true。说明引用ls1和ls2 指向同一个对象,地址相同,堆内存中只存在一个对象。

    单例设计模式的小应用:
    class Test{
            private int num;
            private  static final Test t = new Test();
            private Test(){}
            public static synchronized Test getInstance(){
                return t;
            }
            public int getNum(){
                return num;
            }
            public void setNum(int num){
                this.num = num;
            }
        }
        public class Single{
            public static void main(String[] args) {            
           Test t1 = Test.getInstance(); Test t2 = Test.getInstance(); t1.setNum(10); t2.setNum(20); System.out.println(t1.getNum()); System.out.println(t2.getNum()); } }

    输出结果是:20,20。而不是10,20,因为t1和t2指向同一个对象,t2.setNum(20)后面执行,对象的值被修改为20,所以都输出20.


     

    2.单例模式的实现过程:

    1.定义一个这个A类类型的静态变量 aprivate static A a = null;

    2.private + 类名的构造函数,必须是私有的,是保证这个类不能被其它类new出来。

     Private A{}

    3.对外提供一个一个public static A getInstance()的方法,其它类只能通过这个方法来得到这个类A的实例

    4.通过new在本类中,将创建的对象返回

     

    3. 加同步和不加同步的比较

    方法二比方法一更加通用,更加完美,为什么呢?

    因为方法一存在风险,方法一是线程不安全的,在一个B/S项目中,每个HTTP Request请求到J2EE的容器后就创建了一个线程,每个线程创建一个单例对象怎么办?假设这时候我们用方法一,大家看黄色部分,假如这会儿有两个线程A,B, 线程A执行到This.a = new A();在堆上正在申请内存空间,可能需要0.001微秒,就在这0.001微秒之内,线程B执行到 If (a == null),你说这个判断条件是true还是false呢?是true,因为线程A在堆上正在分配内存空间,还没有创建出实例来。那么,线程B也往下走,内存中就有两个a实例了,看看是不是出问题了?如果你这个单例是去拿一个序列号或者创建一个信号资源的时候,会怎么样?业务逻辑混乱!

    数据一致性校验失败!最重要的是你从代码上还看不出什么问题,这才是最要命的!因为这种情况基本上你是重现不了的,不寒而栗吧,那怎么修改?用方法二,方法而通过finalsynchronized 两个关键字解决了以上假设的问题!synchronized 用来解决线程不安全的问题。

     

    4. 单例模式的优缺点:

     

    优点:

     

    1.减少了内存的开支,特别是一个对象需要频繁的创建、销毁时,而且创建和销毁的性能又无法优化,单利模式的优势就非常明显。

     

    2.减少了系统的性能开销,当一个对象的产生需要比较多的资源的时候,如读取配置、产生其它依赖对象时,则可以在应用启动时直接产生一个单例对象,然后永久驻留在内存的方式来解决(在java EE采用单例模式时需要注意JVM垃圾回收机制)

     

    缺点:1..单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。

     

    2.单例模式对测试是不利的。

     

    5. 最佳实践:

     

    单例模式应用非常广泛,如在Spring中,每个Bean默认就是单例singleton的,这样做的优点是Spring容器可以管理这些bean的生命周期,决定什么时候创建出来,什么时候销毁,销毁的时候如何处理,如果采用非单例模式(Prototype),则bean初始化的管理交由J2EE容器,Spring容器不在跟踪管理Bean的生命周期。(自己也在学Spring中用过

     

    更全面的参考文章:https://coolshell.cn/articles/265.html

     

    Face your past without regret. Handle your present with confidence.Prepare for future without fear. keep the faith and drop the fear. 面对过去无怨无悔,把握现在充满信心,备战未来无所畏惧。保持信念,克服恐惧!一点一滴的积累,一点一滴的沉淀,学技术需要不断的积淀!
  • 相关阅读:
    【leetcode】Sum Root to Leaf Numbers(hard)
    【leetcode】First Missing Positive(hard) ☆
    【leetcode】Next Permutation(middle)
    【好玩的应用】QQ连连看辅助工具
    【leetcode】Binary Tree Preorder Traversal (middle)★
    【leetcode】Reverse Words in a String(hard)☆
    【leetcode】Same Tree(easy)
    【leetcode】Factorial Trailing Zeroes(easy)
    【leetcode】Maximum Gap(hard)★
    Behavioral模式之Chain of Responsibility模式
  • 原文地址:https://www.cnblogs.com/200911/p/2709866.html
Copyright © 2020-2023  润新知