php容器设计模式

devtools/2025/1/8 6:33:28/

PHP中的容器设计模式

容器设计模式(Container Design Pattern)在PHP中是一种用于管理对象实例创建、配置和依赖注入的设计模式。这种设计模式的核心思想是将对象的创建和配置过程从应用中抽离出来,交由一个专门的容器类来管理。容器设计模式在PHP框架中被广泛使用,特别是在实现依赖注入(DI)和控制反转(IoC)时。

以下是一个简单的容器使用图

左边部分(Di 容器)

Di 类作为依赖注入容器,管理服务绑定、实例化等操作逻辑。

  • getInstance():获取 Di 类单例实例,确保应用只有一个容器实例运行。
  • get():便捷获取容器中指定服务对应的实例。
  • make():核心创建实例方法,依服务绑定情况(闭包或类等)创建实例。
  • bindTo():用于绑定服务,关联服务名称与具体实现(类、闭包、对象等)。
  • has():检测服务是否已在容器中绑定或实例化。
  • remove():卸载服务,移除容器相关列表里服务的绑定和实例信息。
  • delete():执行删除具体服务记录操作。

中间部分(ArrayAccess 接口)

Di 类实现 ArrayAccess 接口,按其规则让实例可像数组般被访问。

  • offsetExists():判断服务名称是否存在,通过调用 has 方法实现。
  • offsetGet():获取指定服务名称对应的实例,内部调用 make 方法。
  • offsetSet():设置服务绑定关系,实际调用 bindTo 方法操作。
  • offsetUnset():移除服务绑定等信息,调用 remove 方法执行。
  • getIterator():返回已实例化对象迭代器,便于遍历。
  • count():返回已实例化对象数量,统计存储实例数组的元素个数。

右边部分(具体实现类等)

此部分是服务绑定对应的具体实现内容。若绑定类名,容器用反射机制(如 newInstance 或 newInstanceArgs 操作)实例化;若绑定闭包,获取实例时执行闭包生成对应实例对象。

容器实现代码

php"><?phpuse ArrayAccess;
use ArrayIterator;
use Closure;
use ReflectionClass;
use ReflectionException;class Di implements ArrayAccess
{protected static $instance;protected $instances = []; // 已实例化类的存储数组protected $bind = []; // 服务列表,存储服务名称与对应的类、闭包等绑定关系// 单例模式,获取容器的唯一实例,防止多次实例化public static function getInstance(){if (self::$instance) {return self::$instance;}static::$instance = new static();return static::$instance;}// 获取指定抽象服务(类名等标识)对应的实例public static function get($abstract, $vars = []){return static::getInstance()->make($abstract, $vars);}// 创建并返回指定抽象服务对应的实例,核心方法之一public function make($abstract, $vars = []){// 先从已经实例化的列表中查找,若存在则直接返回该实例if (isset($this->instances[$abstract])) {return $this->instances[$abstract];}// 检测有没有注册该服务,如果未注册则返回 nullif (!isset($this->bind[$abstract])) {return null;}$concrete = $this->bind[$abstract]; // 获取对象具体注册内容$obj = null;// 若绑定的是匿名函数(闭包),则通过传入参数调用该闭包来创建实例if ($concrete instanceof Closure) {$obj = call_user_func_array($concrete, $vars);} elseif (is_string($concrete)) { // 如果是字符串,表示类名try {$class = new ReflectionClass($concrete);if (empty($vars)) {// 无参数实例化类$obj = $class->newInstance();} else {// 带参数的类实例化,使用反射机制解析参数并创建实例$obj = $class->newInstanceArgs($vars);}} catch (ReflectionException $e) {// 处理反射过程中可能出现的异常,比如类不存在等情况throw new \Exception("Error creating instance for '$abstract': ".$e->getMessage());}}// 将新创建的实例存储到已实例化列表中(如果需要单例模式,后续获取会直接返回此实例)$this->instances[$abstract] = $obj;return $obj;}// 绑定服务,可以传入多种形式的参数来建立服务与对应实现的绑定关系public function bindTo($abstract, $concrete = null){if (is_array($abstract)) {// 如果传入的是数组,合并到已有的服务绑定列表中$this->bind = array_merge($this->bind, $abstract);} elseif ($concrete instanceof Closure) {// 如果传入的是闭包,将服务名称与闭包绑定$this->bind[$abstract] = $concrete;} elseif (is_object($concrete)) {// 如果传入的是对象,将其作为对应服务的实例存储(可用于单例等情况)if (isset($this->bind[$abstract])) {$abstract = $this->bind[$abstract];}$this->instances[$abstract] = $concrete;} else {// 普通的服务名称与类名(字符串形式)绑定$this->bind[$abstract] = $concrete;}return $this;}// 检测是否已经绑定了指定的服务(通过服务名称判断)public function has($abstract){return isset($this->bind[$abstract]) || isset($this->instances[$abstract]);}// 卸载指定的服务,从已绑定和已实例化的相关列表中移除public function remove($abstract){return static::getInstance()->delete($abstract);}public function delete($abstract){unset($this->instances[$abstract]);unset($this->bind[$abstract]);return true;}// 实现 ArrayAccess 接口的方法,用于判断指定偏移量(服务名称)是否存在public function offsetExists($offset){return $this->has($offset);}// 实现 ArrayAccess 接口的方法,用于获取指定偏移量(服务名称)对应的实例public function offsetGet($offset){return $this->make($offset);}// 实现 ArrayAccess 接口的方法,用于设置指定偏移量(服务名称)与对应的值(绑定关系等)public function offsetSet($offset, $value){$this->bindTo($offset, $value);}// 实现 ArrayAccess 接口的方法,用于移除指定偏移量(服务名称)的绑定关系等public function offsetUnset($offset){return $this->remove($offset);}// 实现可迭代接口的方法,返回已实例化对象的迭代器,方便遍历已实例化的对象public function getIterator(){return new ArrayIterator($this->instances);}// 实现可数接口的方法,返回已实例化对象的数量public function count(){return count($this->instances);}
}

http://www.ppmy.cn/devtools/148529.html

相关文章

react 的性能优化

React 的性能优化可以分为多个方面,包括组件渲染优化、数据管理优化、网络优化以及工具和最佳实践的使用。以下是详细的性能优化方案: 一、渲染优化 1. 避免不必要的重新渲染 React.memo 对组件进行浅比较,防止组件在父组件重新渲染时无意义的重新渲染。 const ChildCom…

ubuntu 22.04安装ollama

1. 顺利的情况 按照官网的提示&#xff0c;执行下面的命令&#xff1a; curl -fsSL https://ollama.com/install.sh | sh如果网络畅通&#xff0c;github访问也没有问题&#xff0c;那就等待安装完成就行 2. 不顺利的情况 由于众所周知的情况&#xff0c;国内网络访问githu…

基于单片机的核辐射探测系统设计(论文+源码)

1总体设计 众所周知&#xff0c;核辐射对于动植物有着具体的危险&#xff0c;其影响的不仅仅是物种本身还会因为基因变异等原因&#xff0c;影响到下一代。因此在核能的使用过程中&#xff0c;对核辐射进行检测&#xff0c;确保工作人员在一个安全的环境进行工作&#xff0c;非…

组合模式详解

组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你将对象组合成树状结构以表示“部分-整体”的层次结构。组合模式使得客户可以统一地对待单个对象和组合对象。以下是对组合模式的详解&#xff1a; 定义 组合模式&#xff08;Compos…

CAD 精简多段线顶点——cad c# 二次开发

效果如下&#xff1a; 部分代码如下&#xff08;须完善&#xff09;&#xff1a; public static void DD(){using var tr new DBTrans();// CreateSimplePolyline3d();//*****polyline2d转polyline开始//tr.Editor.GetEntities<Polyline2d>(out List<Polyline2d> …

AWS EMR基础知识

EMR Overview 知识点&#xff1a;EMR是可简化大数据框架运行的托管集群平台&#xff0c;能以可扩展且具成本效益的方式处理和分析大量数据&#xff0c;应用于大数据分析、数据处理、机器学习、数据湖和数据仓库等场景。注意事项&#xff1a;根据业务需求选择合适的使用场景&am…

数据库工程师进阶秘籍:云计算基础知识题目精选与答案(附PDF)

【单选题】1、将基础设施作为服务的云计算服务类型是&#xff08;&#xff09;。 A. IaaS B. PaaS C. SaaS D. 以上都不是 正确答案&#xff1a;A 答案解析&#xff1a;本题考查云计算的服务类型。基础设施即服务IaaS&#xff08;Infrastructure as a Service&#xff09;&…

Spring boot对接安全证书

Let’s Encrypt 证书 macOS 在 macOS 上可以直接使用 Homebrew 安装 Certbot&#xff0c;并按照以下步骤生成 Let’s Encrypt 证书并配置到 Spring Boot 项目中。 1. 安装 Certbot 在 macOS 上使用 Homebrew 安装 Certbot&#xff1a; brew install certbot2. 使用 Certbo…