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

    单件模式:确保一个类只有一个实例,并提供全局访问点。

      这一站我们来到了单件模式(Singleton Pattern):用来创建独一无二的,只有一个实例的对象的入场券。告诉大家一个好消息,单件模式的类图算是所有设计模式的类图中最简单的,事实上,它的类图上只有一个类!但是,可不要兴奋过头,尽管从类设计的视角来说它很简单,但是实现上还是会遇到相当多的波折。所以,系好安全带,我们出发咯!

      如何创建一个对象?

      new MyObject();

      万一另一个对象想创建MyObject()会怎样?可以再次new MyObject吗?

      是的,当然可以。

      所以,一旦有一个类,我们是否都能够多次地实例化它?

      如果是公开的类,就可以。

      如果不是的话,会怎样?

      如果不是公开类,只有同一个包内的类可以实例化它,但是仍可以实例化它多次。

      嗯!有意思!你知道的可以这样做吗?

    public MyClass {
        
        private MyClass() {}
    
    }

      我没想过。但是,这是合法的定义,有一定的道理。

      怎么说呢?

      我认为含有私有的构造器的类不能被实例化。

      有可以使用私有的构造器的对象吗?

      嗯,我想MyClass内的代码是唯一能调用此结构的代码。但是这有不太合乎常理。

      为什么?

      因为必须有MyClass类的实例才能调用MyClass构造器,但是因为没有其他类能够实例化MyClass,所以我们得不到这样的实例。这是“鸡生蛋,蛋生鸡”的问题。我可以在MyClass类型的对象上使用MyClass构造器,但是在这之前,必须有一个MyClass实例。在产生MyClass实例之前,又必须在MyClass实例内才能调用私有的构造器......

      嗯!我有个想法。你认为这样如何?

    public MyClass {
        
        public static MyClass getInstance() {
        }
    
    }    

      MyClass有一个静态方法。我们可以这样调用这个方法:MyClass.getInstance();

      为何调用的时候以MyClass的类名,而不是对象名?

      因为getInstance()是一个静态方法,换句话说,是一个“类”方法,你需要使用类名。

      有意思。假如把这些合在一起“是否”就可以初始化一个MyClass?

      

    public MyClass {
        
        private MyClass() {}
        
        public static MyClass getInstance() {
              return new MyClass()
        } 
        
    }

      当然可以。

      好了,你能想出第二种实例化对象的方式吗?

      MyClass.getInstance();

      你能完成代码使MyClass只有一个实例被产生吗?

       嗯,大概可以吧......

    public class Singleton {//把MyClass改名为Singleton
        private static Singleton uniqueInstance;//利用一个静态变量来记录Singleton类的唯一实例
            //这里是其他的实例化变量
        private Singleton() {}//把构造器声明为私有化,只有Singleton类内才可以调用构造器
        public static Singleton getInstance(){//用getInstance()方法实例化对象,并返回这个实例
            if(uniqueInstance == null){
                uniqueInstance = new Singleton();
            }
            return uniqueInstance;
        }
          //这里是其他的方法  
    }

      我们来看看单件模式的类图吧!

      

      我们遇到麻烦了!遭遇到多线程的时候竟然能够完成两个实例化。

      没关系,我们还有办法!利用synchronized关键字可以解决多线程冲突问题。

    public class Singleton {
        private static Singleton uniqueInstance;
        private Singleton() {}
        public static synchronized Singleton getInstance(){
            if(uniqueInstance == null){
                uniqueInstance = new Singleton();
            }
            return uniqueInstance;
        }
    }

       但是似乎同步getInstance()的做法将拖垮性能。

       1.如果getInstance()的性能对应用程序不是很关键,就什么都不要做。没错你的应用程序如果能够接受额外的负担,就忘记这件事吧。同步getInstance()的方法既简单又有效。但是你必须知道,同步一个方法可能造成程序执行效率下降100倍。因此,如果getInstance()使用频繁的话,就需要考虑其他方法了

      2.使用“急切”创建实例,而不用延迟实例化的做法

    public class Singleton {
        private static Singleton uniqueInstance = new Singleton();//急切实例化,保证了多线程安全。
        
        private Singleton() {}
        
        public static Singleton getInstance(){
            return uniqueInstance;//已经有实例了,直接返回
        }
    }

      3.用“双重检查加锁”,在getInstance()中减少使用同步

      

    public class Singleton {
        private volatile static Singleton uniqueInstance;
        //volatile关键字确保:当 uniqueInstance变量被初始化 Singleton实例时,
        //多线程正确地处理 uniqueInstance变量
        
        private Singleton() {}
        
        public static Singleton getInstance(){
            if(uniqueInstance == null){//注意只有第一次才彻底执行下面全部的代码
                synchronize(Singleton.class){
                    if(uniqueInstance == null){//进入区块之后,如果仍是null,则创建实例
                    uniqueInstance = new Singleton();
                    }
                }
            }
            return uniqueInstance;
        }
    }

      上面这个做法可以帮你大大地减少getInstance()的时间消耗.

    wǒ bú xìn nǐ huì zhè mē wú liáo dē bǎ wǒ zhè jù huà dú yí biàn . rú guǒ nǐ zhēn dē dú lē . wǒ zhǐ xiǎng gào sù ni . wǒ xǐ huan ni.

  • 相关阅读:
    宏观经济指标
    Poloniex API 文档
    雪球释老毛推荐的投资者书单
    数字货币开源项目——貔貅
    数字货币量化分析报告_20170905_P
    数字货币量化分析报告_2017-09-05
    数字货币量化分析报告_2017-09-04
    ICO成本价
    Python3使用Print输出带颜色字体
    Ta-lib函数功能列表
  • 原文地址:https://www.cnblogs.com/zpfbuaa/p/5510141.html
Copyright © 2011-2022 走看看