单例模式

来源:互联网 发布:1.5cm胆结石知乎 编辑:程序博客网 时间:2024/04/30 04:27

                                        Singleton pattern 单例模式

vc做过程序设计的人,一定记得MainFrame中的构造函数的默认属性为private,以及在SDI模式下doc类&CView类默认情况下的构造函数也是私有的。
生活中存在许多单例模式的例子,比如从北京的上海的铁路线只有一条,当然修两条未尝不可,只是这样作没有太大的必要,一是需求量尚未达到要求,二是反倒会带来不少的麻烦(时间——列车调度表)。需要说明的一点:如果一个类的构造函数是public属性,它也能实现单例模式,只不过将创建对象的权利完全移交给了类的使用者。而申明private后,外部没有了这种权利,自然也就避免了某种形式的错误。又如在数据库访问操作中的Connection对象。我们总是在对数据库访问的操作的一开始建立连接,而以后的操作都是在这个连接上进行的,而不需要重新进行连接,不仅减少了不必要的资源消耗,还加快了访问操作的速度。
单例模式类建模
构造函数的private属性使得类外部访问操作不具有创建此类对象的权利,对象的创建只能是放到类Singleton的内部进行。那么为了让外部能访问到这个对象,我们必须给他提供一个函数getInstance()返回这个内部创建的对象。由于实际的访问可能要多次进行,所以需要对getInstance()创建的对象进行保存,由于getInstance()函数的static属性,保存这个对象的成员变量也应该是static属性。
 
单例类
publicclass Singleton {
   private static Singleton sig
   private Singleton(){}
   public   static Singleton getSingleInstance(){
      if(null==sig){
        sig = new Singleton() ;
      }
      returnsig ;
   }
}
如你你要测试上面的单例模式是否正确的话可以通过
getInstanceString name)函数传递一个参数给构造函数
publicclass Singleton {
   private static Singleton sig
   private String name ;
   private Singleton(String str){
      this.name = str ;
   }
   publicstatic Singleton getInstance(String str){
      if(null==sig){
        sig = new Singleton(str) ;
      }
      returnsig ;
   }
   public String getName(){
      returnthis.name ;
   }
}
 
测试类
publicclass MainTest {
   publicstaticvoid main(String[] args) {
      // TODO Auto-generated method stub
      Singleton sig1 = Singleton.getInstance("fist object");
      Singleton sig2 = Singleton.getInstance("second object");
       System.out.println(sig1.getName());
       System.out.println(sig2.getName());
   }
}
输出结果fist object
fist object
上述的Singleton类可以在实际应用中实现单例模式,我们来来看看多线程下可能出现那种情况:我们假设第一个线程刚刚执行了条件的判断单尚未进行对象的创建,测试线程发生了跳转,下一个线程也执行到条件判断后,线程发生跳转,如此下去线程又跳回到第一个线程。。。。。这样进行下去下一次轮到时,各个线程将分别创建自己的对象。
if(null==sig){
        sig = new Singleton(str) ;跳转处
}
你可能会问这样的概率实在太低,但是请记住:
If anything can go wrong, it will
所以为了避免在多线程的编程中出现多个对象,建议大家在getInstance()方法的前面加上synchronized关键字,对关键字保证了,getInstance()方法中不会出现线程之间的转换。这样就更加安全的保证了单例模式的执行。
 
单例类
publicclass Singleton {
   private static Singleton sig
   private String name ;
   private Singleton(String str){
      this.name = str ;
   }
   publicstaticsynchronized Singleton getInstance(String str){
      if(null==sig){
        sig = new Singleton(str) ;
      }
      returnsig ;
   }
   public String getName(){
      returnthis.name ;
   }
}
测试线程类
publicclass SetThread implements Runnable {
    Thread   thread
    public SetThread(){
     Singleton sig= Singleton.getInstance("OBJ 1");
     System.out.println(sig.getName()) ;
     thread = new Thread(this) ;
     thread.start();
    }
   @Override
   publicvoid run() {
      // TODO Auto-generated method stub
      Singleton sig2= Singleton.getInstance("OBJ 2");
       String Str2 = sig2.getName() ;
       System.out.println(Str2) ;
   }
   publicstaticvoid main(String[] args) {
      // TODO Auto-generated method stub
      SetThread thr = new SetThread() ;
   }
}
 
输出结果:OBJ 1
OBJ 1
 
备注你可能在去掉synchronized关键字之后也能出现上面的结果,但是需要说明:程序某次运行正确,并不能代表程序本生没有bug,多数情况下只是bug没有表现出来巴了。
原创粉丝点击