zoukankan      html  css  js  c++  java
  • 单例模式

    GOF中最简单的一个模式,只涉及到一个类。比如线程池、缓存等这些对象在应用只能被实例化一次,如果实例化多次,有可能会造成不可预测的后果。何谓单例?答曰:该类的对象只能被实例化一次。


    程序猿:如果只是为了让对象被创建一次,那我们直接把对象放在全局变量在不就可以解决这类问题了?
    大师:放在全局中的确可以解决该类问题,但还是存在一些缺陷。
    程序猿:什么缺陷?
    大师:你把对象放在全局变量中,意味着在程序启动的时候就必须要实例化,如果该对象创建的时间比较长而且
    在创建出来的时候不一定就用得上,那就会消耗资源,全局静态变量的确是能解决问题,但单例模式也一个不错
    的选择,你可以在需要的时候再创建它。

    单例模式实现



          类如何被实现化 :    new MyInstance(); 如果另一个对象想创建怎么办?当然还是可以通过new 来再一次进行创建。只要是公共类,就可以被重复创建。那如果不是公共类又是一种什么情况呢?只有同一个包中的类可以实例化它,但是也可以被多次实例化。
          如果有多年经验的你可能会想到 private MyInstance(),对了,如果应用私有构造函数,那就不能通过
    new来随心所欲的进行实例化了。那你可能又有一个问题要问了,不能通过new来实例化对象,那通过什么方式来实例化对象?来看一下下面的代码你就会晃然大悟了。

    1 public class MyInstance{
    2 
    3        private MyInstance(){
    4        }
    5        //
    6        public static MyInstance getMyInstance(){
    7               return new MyInstance();
    8        }
    9 }
    View Code

    通过getMyInstance方法,就可以进行实例化了,但这个跟直接跟通过new创建有何区别呢,代码还没有完成,我们来进一步完善

    public class MyInstance{
    
          private static MyInstance instance;
          //通过私有构造函数,防止用户通过默认的构造函数来实例化对象
          private MyInstance(){}  
          public static MyInstance getMyInstance(){
                 if(instance==null){
    System.out.print("myinstance is null"); instance
    =new MyInstance();
    }
    return instance; } }

    下面代码测试一下是否工作正常,建一个类来实例化MyInstance,然后在main中调用,

    1 public class Test {
    2     public void business(){
    3         MyInstance _instand1 = MyInstand.getMyInstance();
    4         MyInstance _instand2 = MyInstand.getMyInstance();
    5     }
    6 }
    View Code
    1 public class Main {
    2 
    3     public static void main(String[] args) {
    4          //TODO Auto-generated method stub
    5          Test t = new Test();
    6          t.business();
    7     }
    8 
    9 }
    View Code

    代码执行后,你会看到控制台只输出一条“Myinstance is null“,说明MyInstance只被实例化了一次。到此单例模式基本完成,为什么是基本完成而不是已完成了呢。要知详情请看后文。

    得意得太早


     现实永远比想象残酷,当你以为上面的代码已完成交给你的其他猿类使用时,末日来临了。请猿们看下面的代码,看看将会发生什么。

     1 public class Test extends Thread{
     2 
     3     @Override
     4     public void run() {
     5         // TODO Auto-generated method stub
     6               super.run();
     7                   MyInstance _instance = MyInstanece.getMyInstance();
     8     }
     9 }
    10 
    11 
    12 public class Main {
    13 
    14     /**
    15      * @param args
    16      */
    17     public static void main(String[] args) {
    18         // TODO Auto-generated method stub
    19          Test t1 = new Test();
    20          t1.start();
    21          Test t2 = new Test();
    22          t2.start();
    23     }
    24 
    25 }
    View Code

    执行以上代码发现了什么?出现了两条“myinstand is null”,你测试的没事,是出现两次,这就是线程做得手脚。

    解决


    既然是线程引起的,那我们就解决线程问题,在MyInstance的getMyInstance方法前加上“synchronized”,让线程同步,这种灾难将得到解决

     1 public class MyInstance {
     2     private static MyInstance _instance;
     3     private MyInstance(){}
     4     public static synchronized MyInstand getMyInstance(){
     5         if(_instance==null){
     6             System.out.print("myinstand is null");
     7             _instance =new MyInstance();
     8         }
     9         return _instance;
    10     }
    11 }
    View Code

    现在再执行代码,发现只实例化了一次。

    一波未平一波又起


    通过线程同步解决了上面出现的问题,但新的问题又出现在了我们的眼前,那就是程序的性能降低了。--未完待续

  • 相关阅读:
    Unix命令大全
    vs2008 与 IE8出现的兼容性问题
    Java 创建文件、文件夹以及临时文件
    如何修改Wamp中mysql默认空密码
    PAT 乙级真题 1003.数素数
    Tags support in htmlText flash as3
    DelphiXE4 FireMonkey 试玩记录,开发IOS应用 还是移植
    10 Great iphone App Review sites to Promote your Apps!
    HTML tags in textfield
    Delphi XE4 IOS 开发, "No eligible applications were found“
  • 原文地址:https://www.cnblogs.com/sunrfun/p/3635211.html
Copyright © 2011-2022 走看看