PHP设计模式之对象池模式

Table of Contents

关于对象池

传统的php开发模式基本用不到对象池的,当请求完毕时,我们自己创建的所有对象等都会自动销魂。但是,如果常驻内存运行的开发模式,比如使用了swoole,那么使用对象池模式是非常有用的。

对象池模式是一种提前准备了一组已经初始化了的对象『池』而不是按需创建或者销毁的创建型设计模式。对象池的客户端会向对象池中请求一个对象,然后使用这个返回的对象执行相关操作。当客户端使用完毕,它将把这个特定类型的工厂对象返回给对象池,而不是销毁掉这个对象。

在初始化实例成本高,实例化率高,可用实例不足的情况下,对象池可以极大地提升性能。在创建对象(尤其是通过网络)时间花销不确定的情况下,通过对象池在可期时间内就可以获得所需的对象。

无论如何,对象池模式在需要耗时创建对象方面,例如创建数据库连接,套接字连接,线程和大型图形对象(比方字体或位图等),使用起来都是大有裨益的。在某些情况下,简单的对象池(无外部资源,只占内存)可能效率不高,甚至会有损性能。

实现

首先,我们需定义三个方法,分别如下:

  • get 方法获取连接(连接池未满时会创建新的连接)
  • put 方法回收连接
  • fill 方法填充连接池(提前创建连接)
class Obj
{
   private $rand;

   public function __construct()
  {
       $this->rand = mt_rand(10000, 99999);
  }

   public function getTime ()
  {
       return $this->rand;
  }
}

class ObjPool
{
   private $freePools = [];
   private $usedPools = [];

   public function fill()
  {
       for ($i = 0; $i < 100; $i ++) {
           $obj = new Obj();
           $this->freePools[spl_object_hash($obj)] = $obj;
      }
  }

   public function get () : Obj
  {
       if (!count($this->freePools)) {
           throw new \Exception('pool empty');
      }

       $obj = array_pop($this->freePools);
       $this->usedPools[spl_object_hash($obj)] = $obj;

       return $obj;
  }

   public function put (Obj $obj)
  {
       $hashId = spl_object_hash($obj);

       if (isset($this->usedPools[$hashId])) {
           unset($this->usedPools[$hashId]);
           $this->freePools[$hashId] = $obj;
      }
  }

   public function __get ($name)
  {
       return $this->$name ?? null;
  }
}

文章部分内容参考自:https://learnku.com/docs/php-design-patterns/2018/Pool/1491