当前位置:  开发笔记 > 编程语言 > 正文

PHPV5.3用延后静态绑定搞活面向对象编程

PHPV5.3通过其延后静态绑定(LSB)特性解决了面向对象编程(OOP)的一些问题。了解LSB如何修复PHP的OOP编程问题以及如何实现需要使用LSB的一些众所周知的面向对象设计模式。面向对象编程(OOP)可让开发人员通过使用数据抽象、封装、模块化、多态">

PHP V5.3 通过其延后静态绑定(LSB)特性解决了面向对象编程(OOP)的一些问题。了解 LSB 如何修复 PHP 的 OOP 编程问题以及如何实现需要使用 LSB 的一些众所周知的面向对象设计模式。
面向对象编程(OOP)可让开发人员通过使用数据抽象、封装、模块化、多态性和继承减少和简化代码 — 在对 OOP 有着深刻的理解的前提下。对 OOP 特性的了解还让 PHP 编码者得以利用设计模式 — 一些众所周知的用来解决常见问题的算法。PHP 自 V3.0 就已经提供了 OOP 功能,但直到 V5.3 到来时,PHP 的 OOP 实现内的怪异之处还是会阻止一些常见设计模式的使用。随着 PHP V5.3 的延后静态绑定(LSB)特性的出现,这些怪异之处均已彻底消失。

本文向您介绍了在 PHP V5.3 出现之前,存在问题的一些设计模式,解释了这些模式为何不能工作。然后展示了 PHP V5.3 的 LSB 特性,并给出了单例和活动记录设计模式。

重新回顾 OOP

如果您过去曾接触过 PHP OOP,那么很可能会出于以下原因而决定不使用它:

读过诸多宣称 PHP OOP 有问题的博文中的一条。

曾尝试实现一个简单的设计模式,但没有成功。

而对于 PHP V5.3,有关 OOP 的博文都是正面的,并且 PHP OOP 的问题在很大程度上已得到解决。是时候重回 PHP OOP 了。通过本文,您将看到在 V5.3 出现之前曾存在问题的一些设计模式:单例、生成器、工厂方法和活动记录。

单例、生成器和工厂方法设计模式被视为是 创建型 的模式,因它们可协助对象的构建。单例模式可能是最常用的 OOP 设计模式之一了 ;它限制了一个类的对象实例数只能为 1。比如数据库连接池就是单例设计模式的一个例子:我们一般不想让应用程序具有连接池类的多个资源密集型实例。

在需要分离复杂对象的构建和表示时,就需要用到生成器设计模式,您可以使用相同的构造过程来创建多个对象。生成器模式的实现可以很复杂,但一旦生成器可用,它就可以简化生成器所创建对象的构造和使用。具有输出 HTML、XML 或 PDF 能力的转变器就是需要使用生成器的一个例子。

而工厂方法模式,顾名思义,定义的是一个用来大量产出对象的方法的实现。您可以在应用程序需要创建其类型依赖于子类的实现的对象时,使用工厂方法模式。

活动记录模式则可用来在域类内包装关系数据库持久性方法。一个活动记录的每个实例都关系到数据库内的特定行。这个类包含了要插入、删除和更新数据库内的一行或多个行的方法。活动记录设计模式是由 Martin Fowler 在 Patterns of Enterprise Application Architecture 内定义的,并因在 Ruby on Rails 内的使用而日益流行。

前-LSB 的创建型设计模式实现问题

上述提到的所有这四个设计模式均使用了静态的属性和方法。例如,看一下清单 1 内所示的这个连接池单例。

清单 1. 一个简单的单例

class ConnPool {
private static $onlyOne;
private static $count = 0;
private function __construct() {
// real-world db conn stuff here...
}

public static function getInstance() {
if (!is_object(self::$onlyOne)) {
$klass = __CLASS__;
self::$OnlyOne= new $klass();
self::$count++;
}
return self::$onlyOne;
}
public static function getInstanceCount() {return self::$count;}
}

$db = ConnPool::getInstance();
assert (1 == $db->getInstanceCount());
$db2 = ConnPool::getInstance();
assert (1 == $db2->getInstanceCount());
?>
请注意这个静态的 $onlyOne 变量。该变量被设计用来保存连接池对象的一个实例。$onlyOne 之前的静态修饰符将此变量关系到类本身。$onlyOne 变量是一个类属性,因为其作用域是这个类。而 $onlyOne 属性只有一个实例。当一个属性不具有静态修饰符时,就称其是一个对象属性,因为该属性对类的每个实例都是惟一的。

注意到 ConnPool 的构造函数方法(called __construct)是空的。在一个生产实现中,可以使用该方法来创建数据库连接池的间隔。

静态 getInstance 方法包含单例的模板代码。只有在静态的 $onlyOne 变量为空时,它才会创建一个 $onlyOne 实例。请注意它是如何使用 __CLASS__ 变量来获得类的类型并随即创建该类的一个实例的。

使用 getInstanceCount 方法只是为了证明只创建了连接池的一个实例。清单 1 底部的四行代码则证明无论请求 ConnPool 池类的一个实例多少次,它都会返回相同的对象。

所以, 到目前为止,此单例一切正常 — 直到您决定想要以面向对象的继承树的形式对这个连接池进行子类处理来支持多个数据库。清单 2 显示了这个继承树(为了清晰起见,删除了实例计数器和构造函数代码)。

清单 2. 在没有 LSB 时对单例进行的一次失败尝试

class ConnPool {
private static $onlyOne;
protected static $klass = __CLASS__;

public static function getInstance() {
if (!is_object(self::$onlyOne)) {
self::$OnlyOne= new self::$klass();
}
return self::$onlyOne;
}
}

class ConnPoolAS400 extends ConnPool {
protected static $klass = __CLASS__;
}
$db = ConnPoolAS400::getInstance();
assert ('ConnPoolAS400' == get_class($db)); // fails
?>
为了支持多个类型的单例类,ConnPool 类添加了一个 $klass 静态变量并假设它会在子类中被覆盖。 ConnPoolAS400 子类扩展了 ConnPool 类并提供了 $klass 属性自己的版本。 我们的预期是当 ConnPoolAS400 类的实例创建时,$klass 属性会保存 ConnPoolAS400。但是当执行这些代码时,它不会按预期的那样运行。当 PHP 实用函数 get_class 返回 ConnPool 而不是 ConnPoolAS400 时,代码底部的声明会失败。 问题是 ConnPool 类的 getInstance 方法使用的是它自己的 $klass 属性版而非 ConnPoolAS400 的覆盖版。


推荐阅读
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • gitlab重置password
    ruby没怎么学,自己搭建的gitlab的rootpassword又忘了。幸好看见此帖子,试验okhttp:roland.kierkels.netgitreset-your-git ... [详细]
  • Allegro总结:1.防焊层(SolderMask):又称绿油层,PCB非布线层,用于制成丝网印板,将不需要焊接的地方涂上防焊剂.在防焊层上预留的焊盘大小要比实际的焊盘大一些,其差值一般 ... [详细]
  • 导读:在编程的世界里,语言纷繁多样,而大部分真正广泛流行的语言并不是那些学术界的产物,而是在通过自由发挥设计出来的。和那些 ... [详细]
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了游戏开发中的人工智能技术,包括定性行为和非定性行为的分类。定性行为是指特定且可预测的行为,而非定性行为则具有一定程度的不确定性。其中,追逐算法是定性行为的具体实例。 ... [详细]
  • Android系统移植与调试之如何修改Android设备状态条上音量加减键在横竖屏切换的时候的显示于隐藏
    本文介绍了如何修改Android设备状态条上音量加减键在横竖屏切换时的显示与隐藏。通过修改系统文件system_bar.xml实现了该功能,并分享了解决思路和经验。 ... [详细]
author-avatar
双子汐晨_312
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有