zoukankan      html  css  js  c++  java
  • 设计模式之单例模式探究

          这周好像没安排什么博客任务唉,那就随便写点吧,说说单例模式在php中的玩法好了

          首先吧,单例模式在我们项目开发中经常要用到,比如商城系统的购物车类吧,我们不能每次买完商品后都要创建一个购物车对象吧,这样前边买的商品岂不是被覆盖掉了??卖东西的也会有损失吧,这样岂不是恶心了别人,郁闷了自己??所以嘛,单例模式还是很重要滴!!!!!!

          那我们先写一个类好了,鉴于我比较懒,所以就写个dog类吧,诸位看客不要对号入座哈。

    class Dog
    {
       public $name;
       public $age;
       
       public function __construct($name,$age)
       {
          $this->name=$name;
          $this->age=$age;
       }
    }
    

      学过编程的人都知道,当我们需要某个类的一个实例的时候,基本都是new出来一个(当然还有其它创建方式,在此不一一列举,就以new为例),那么我们来new一下好了

    $dog1=new Dog('小白',6);
    $dog2=new Dog('小明',7);
    

    在上边的代码中,我们new出来了两个对象dog1和dog2,那么在你看来,这是不是一个对象呢?(吐槽:你脑残啊,你都说了是new了俩对象了!!),咳咳,确实是俩对象,那么问题来了,你new一个出来一个新的对象,怎么实现上边所说的单例模式呢???(吐槽:笨蛋,你都说了new一个出来一个新对象,那就不要new了呗),可是,我们怎么才能不new呢?当然,不new怎么产生那个单例对象呢?所以,不new还是不行滴。可是怎么才能解决这个问题呢?(沉思10万年中。。。。。。)

    ----------------------------------------------------------------10万年后--------------------------------------------------------------------------------------

    众所周知,我们在new的时候,都是在调用类的构造函数,来产生一个对象,我们new一个,出来一个新对象,那么,我们就把上边的构造函数改造一下不就好了??废话先不说了,看看代码好了:

    class Dog
    {
       public $name;
       public $age;
       
       protected function __construct($name,$age)
       {
          $this->name=$name;
          $this->age=$age;
       }
    }
    

      看见区别了没?我把构造函数的权限改了,由public改为了protected,这时候你看,这样就没法再new出新对象了。(吐槽:是没法new了,可是你给我生出来那个单例对象啊???)。先别急,我们是没法在外边new出对象了,可是。。。可是。。。我们能在类里边new出来一个啊,在类内部是可以调用被protected保护的构造函数的,于是,代码变成了下边这样:

    class Dog
    {
       public $name;
       public $age;
       
       public function getIns()
       {
          return new Dog('小白',6);
       }
       protected function __construct($name,$age)
       {
          $this->name=$name;
          $this->age=$age;
       }
    }
    

      恩,这样就好多了,我们不让鬼子进村随便new对象了,还提供了一个public的方法,可以创建一个对象,问题好像解决了,那么真的就结束了么??别忘了,我们的获得对象的函数是写在类内部的啊,没有对象我们怎么调用啊?可是话又说过来,有了对象我们还调用它干嘛啊?于是新的问题出现了,我们没法调用产生对象的函数,这真是一个令人忧桑的问题。。。。。。那么我再想想怎么解决吧(沉思10万年中。。。。。。)

    ------------------------------------------------------------------------10万年后-----------------------------------------------------------------------------

          好了,继续说这个问题吧(吐槽:终于睡醒了),我们要产生对象,就要调用类内的函数,可是没有对象,我们又没法调用那个函数(系统陷入了死循环)。那么问题的关键就落在了在没有对象的情况下,怎么调用那个函数上。这时候请打开记忆的阀门,在我们上c++课的时候,老师是不是讲了一个东西,它属于全类,而不属于某个具体的对象??(观众:好像真的有哎,叫什么来着??好像叫static)。。。。Bingo!!!答对了,就是它,我们可以把那个得到对象的函数写成static的是,这样它就成全狗类的了,再也不属于某个对象的私藏物品了(PS:女神是大家的,谁也不能私藏。。。),于是代码出现了:

    class Dog
    {
       public $name;
       public $age;
       
       public static function getIns()
       {
          return new Dog('小白',6);
       }
       protected function __construct($name,$age)
       {
          $this->name=$name;
          $this->age=$age;
       }
    }
    

      问题解决了,我们终于得到了一个单例模式的类,这时候我们满心欢喜的交给了老师,炫耀自己的劳动成果,老师认真看了一下,说:可是,我们每调用一次getIns()函数就产生了一个新的对象,这跟最开始没改的时候有区别嘛???我又看了一下,还真是。。。。。。。。。又回到了最初的起点,记忆中你青涩的脸。。。(吐槽:咳咳,跑题了)。。。

         于是啊,我又陷入了沉思。。。(沉思1万年中。。。(这次少点,别让你看瞌睡了))

    -------------------------------------------------------------------------1万年后------------------------------------------------------------------------------

        终于想明白了,虽然这时候看起来是回到了最初的起点,可还是有很大区别的,你看,代码量起码上去了不是??好吧,不扯淡了,言归正传,我们这时候得到了这么个情况,跟起点最大的区别就是:以前new对象是靠构造函数,现在是靠调用getIns()函数,既然不是构造函数,我们可处理的权限就大多了,我们适当的加入一些逻辑判断就能解决这个问题,不信???让代码说话:

    class Dog
    {
       public $name;
       public $age;
       public static $ins=null;
       
       public static function getIns()
       {
          if(Dog::$ins)
    	  {
    	     return Dog::$ins;
    	  }
          Dog::$ins=new Dog('小白',6);
          return Dog::$ins;
       }
       protected function __construct($name,$age)
       {
          $this->name=$name;
          $this->age=$age;
       }
    }
    

      在上边的代码中,我们加了一个static变量,定义为$ins,用来存储产生的单例对象,在getIns()函数中,我们判断这个$ins对象是否存在且不为空,如果存在且不为空,那么就直接返回它,不然创建一个对象,并把创建的对象给它,告诉下次调用该函数时说对象已经存在了,就不用新new直接返回原先的对象就好了,那么单例对象也就完美(自以为)解决了,这时候拿给老师看,老师欣慰一笑,说:恩,不错,已经基本上能用了。

          可是,如果我用一个新的类叫Dog1,继承你的Dog类,我把构造函数的权限给扩大,改成public,这时候就可以随便new了,你又怎么解决呢??(熟悉php的人知道,在子类继承父类的时候,是能够把父类函数的权限扩大的,也可以维持不变,但不能缩小)。。。。。。。。。。(吐槽:尼玛,这老师跟我有仇啊,我好不容易写个代码容易吗??你还要拆台??),咳咳,要尊敬老师。。。。。。。。。。。。。。。。。。。。。。于是,继续沉思(沉思10万年中。。。。。。。。。。。。。。。。。。。。。。)

    ------------------------------------------------------------------------10万年后-----------------------------------------------------------------------------

        经过十万年的积淀,我终于能够解决这个问题了,怎么解决呢??既然老师要继承我的类,要扩大权限,那事情好办,我就不让它继承了,我在类前边加个final关键字,这样就好了(妈妈再也不用担心有人继承我的类了)。。。。。。(吐槽:感情你睡了十万年就想出来这么个办法啊??),可是,在实际开发中,如果这个类必须要被继承咋办??不然项目会麻烦许多,这时候又改如何解决呢??既然想到了final,为什么不想想它的别的用法呢???脑袋瓜一亮:我可以让别人继承我的类,我不让别人重写我的构造函数不就行了??反正类是我的,自己不愿意继承自己写去。。。。。所以,我把final加到了构造函数上,代码如下:

    class Dog
    {
       public $name;
       public $age;
       public static $ins=null;
       
       public static function getIns()
       {
          if(Dog::$ins)
    	  {
    	     return Dog::$ins;
    	  }
          Dog::$ins=new Dog('小白',6);
          return Dog::$ins;
       }
       protected final function __construct($name,$age)
       {
          $this->name=$name;
          $this->age=$age;
       }
    }
    

      于是,经过31万年的努力,终于写出来这个单例对象了,为了防止老师再挑别的毛病,我还是不去找他看了,我自己藏着好了!!(吐槽:。。。。。。)

  • 相关阅读:
    openldap
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P1200 [USACO1.1]你的飞碟在这儿Your Ride Is He…
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P2141 珠心算测验
    Java实现 洛谷 P1567 统计天数
    Java实现 洛谷 P1567 统计天数
  • 原文地址:https://www.cnblogs.com/jakii/p/4419597.html
Copyright © 2011-2022 走看看