Constructor Prototype Pattern 原型模式(PHP示例)
当一个类大部分都是相同的只有部分是不同的时候,如果需要大量这个类的对象,每次都重复实例化那些相同的部分是开销很大的,而如果clone之前建立对象的那些相同的部分,就可以节约开销。
针对php的一种实现方式就是__construct()和initialize函数分开分别处理这个类的初始化,construct里面放prototype也就是公共的部分,initialize里面是每个对象特殊的部分。这样我们先建立一个类不initialize,以后每次clone这个类再进行initialize就可以了。
在zend framework官方手册里面提到了这个http://framework.zend.com/manual/2.0/en/user-guide/database-and-models.html,但是没有细讲,下面我来分析一下
一、引入
在zf2的model里面有一个albumTable类,相当于一个操作数据库动作的助手类,里面用到了tablegateway。
为了每次初始化albumtable都是相同的一个类,将初始化工作放到了根目录的module.php文件的getServiceConfig(),其中用到工厂模式,并且通过回调函数,当每次ServiceManager($sm)需要实例化一个对象的时候会自动调用创建一个alumTable。下面代码我们可以看出,创建一个albumTable还需要用相同的方式创建一个AlbumTableGateWay,这个类就用到了我们所要讲的原型模式。
二、代码详解
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> getServiceConfig() { </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">array</span><span style="color: #000000;">( </span>'factories' => <span style="color: #0000ff;">array</span><span style="color: #000000;">( </span>'Album\Model\AlbumTable' => <span style="color: #0000ff;">function</span>(<span style="color: #800080;">$sm</span><span style="color: #000000;">) { </span><span style="color: #800080;">$tableGateway</span> = <span style="color: #800080;">$sm</span>->get('AlbumTableGateway'<span style="color: #000000;">); </span><span style="color: #800080;">$table</span> = <span style="color: #0000ff;">new</span> AlbumTable(<span style="color: #800080;">$tableGateway</span><span style="color: #000000;">); </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$table</span><span style="color: #000000;">; }</span>, 'AlbumTableGateway' => <span style="color: #0000ff;">function</span> (<span style="color: #800080;">$sm</span><span style="color: #000000;">) { </span><span style="color: #800080;">$dbAdapter</span> = <span style="color: #800080;">$sm</span>->get('Zend\Db\Adapter\Adapter'<span style="color: #000000;">); </span><span style="color: #800080;">$resultSetPrototype</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> ResultSet(); </span><span style="color: #800080;">$resultSetPrototype</span>->setArrayObjectPrototype(<span style="color: #0000ff;">new</span> Album());<span style="color: #008000;">//</span><span style="color: #008000;">这个就是一个不变的原型</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span> TableGateway('album', <span style="color: #800080;">$dbAdapter</span>, <span style="color: #0000ff;">null</span>, <span style="color: #800080;">$resultSetPrototype</span>);<span style="color: #008000;">//</span><span style="color: #008000;">传入到TableGateWay的构造函数中去</span> },<span style="color: #000000;"> )</span>,<span style="color: #000000;"> ); }</span>
注意并不是TableGateWay运用了原型模式而是ResultSet这个类运用了。每当tablegateway调用select()或者insert()等方法的时候都会建立一个ResultSet用来表示结果,这些ResultSet中公共部分被clone,而独特的部分类如data就会被initialize。
三、更多代码示例
为了更清晰得了解这个原型,我们先抛开zend这个大框架,看一个完整的代码示例。示例来自
<a href="http://ralphschindler.com/2012/03/09/php-constructor-best-practices-and-the-prototype-pattern">PHP Constructor Best Practices And The Prototype Pattern</a>
这篇文章关于prototype pattern的部分前半部分其实是混杂怎样在构造函数中运用继承来提高扩展性,两个模式看起来可能不太好理解,我们直接看最后的代码关于prototype pattern的部分。
<span style="color: #000000;">php</span><span style="color: #008000;">//</span><span style="color: #008000;">框架中很常见的adapter类,用来适配各种数据库,封装一些基本数据库连接操作。//相当于上面代码中的adapter类</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> DbAdapter { </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> fetchAllFromTable(<span style="color: #800080;">$table</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$arrayOfData</span><span style="color: #000000;">; }}</span><span style="color: #008000;">//</span><span style="color: #008000;">运用prototype pattern的类,注意construct和initialize是分开的//相当于上面zend 代码里面的ResultSet类</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> RowGateway { </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __construct(DbAdapter <span style="color: #800080;">$dbAdapter</span>, <span style="color: #800080;">$tableName</span><span style="color: #000000;">) { </span><span style="color: #800080;">$this</span>->dbAdapter = <span style="color: #800080;">$dbAdapter</span><span style="color: #000000;">; </span><span style="color: #800080;">$this</span>->tableName = <span style="color: #800080;">$tableName</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> initialize(<span style="color: #800080;">$data</span><span style="color: #000000;">) { </span><span style="color: #800080;">$this</span>->data = <span style="color: #800080;">$data</span><span style="color: #000000;">; } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * Both methods require access to the database adapter * to fulfill their duties </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> save() {} </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> delete() {} </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> refresh() {}}</span><span style="color: #008000;">//</span><span style="color: #008000;">相当于上面代码中的TableGateway类,关于gateway可以具体去了解一下。</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> UserRepository { </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __construct(DbAdapter <span style="color: #800080;">$dbAdapter</span>, RowGateway <span style="color: #800080;">$rowGatewayPrototype</span> = <span style="color: #0000ff;">null</span><span style="color: #000000;">) { </span><span style="color: #800080;">$this</span>->dbAdapter = <span style="color: #800080;">$dbAdapter</span><span style="color: #000000;">; </span><span style="color: #800080;">$this</span>->rowGatewayPrototype = (<span style="color: #800080;">$rowGatewayPrototype</span>) ? <span style="color: #0000ff;">new</span> RowGateway(<span style="color: #800080;">$this</span>->dbAdapter, 'user'<span style="color: #000000;">) } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> getUsers() { </span><span style="color: #800080;">$rows</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">(); </span><span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$this</span>->dbAdapter->fetchAllFromTable('user') <span style="color: #0000ff;">as</span> <span style="color: #800080;">$rowData</span><span style="color: #000000;">) { </span><span style="color: #800080;">$rows</span>[] = <span style="color: #800080;">$row</span> = <span style="color: #0000ff;">clone</span> <span style="color: #800080;">$this</span>-><span style="color: #000000;">rowGatewayPrototype; </span><span style="color: #800080;">$row</span>->initialize(<span style="color: #800080;">$rowData</span><span style="color: #000000;">); } </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$rows</span><span style="color: #000000;">; }}</span>
这几个类其实和上面zend代码中的类是对应的
Dbadapter -- adpater
RowGateWay -- ResultSet
UserRepository - TableGateWay
具体看代码中的注释。
这里的RowGateWay可以很明显的看出在getusers中需要大量的实例化,那么原型模式就是很必要的了。
下面是运用这个类的代码
<span style="color: #0000ff;">class</span> ReadWriteRowGateway <span style="color: #0000ff;">extends</span><span style="color: #000000;"> RowGateway { </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __construct(DbAdapter <span style="color: #800080;">$readDbAdapter</span>, DbAdapter <span style="color: #800080;">$writeDbAdapter</span>, <span style="color: #800080;">$tableName</span><span style="color: #000000;">) { </span><span style="color: #800080;">$this</span>->readDbAdapter = <span style="color: #800080;">$readDbAdapter</span><span style="color: #000000;">; parent</span>::__construct(<span style="color: #800080;">$writeDbAdapter</span>, <span style="color: #800080;">$tableName</span><span style="color: #000000;">); } </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> refresh() { </span><span style="color: #008000;">//</span><span style="color: #008000;"> utilize $this->readDbAdapter instead of $this->dbAdapter in RowGateway base implementation</span><span style="color: #000000;"> }}</span><span style="color: #008000;">//</span><span style="color: #008000;"> usage:</span><span style="color: #800080;">$userRepository</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> UserRepository( </span><span style="color: #800080;">$dbAdapter</span>, <span style="color: #0000ff;">new</span> ReadWriteRowGateway(<span style="color: #800080;">$readDbAdapter</span>, <span style="color: #800080;">$writeDbAdapter</span>, 'user'<span style="color: #000000;">));</span><span style="color: #800080;">$users</span> = <span style="color: #800080;">$userRepository</span>-><span style="color: #000000;">getUsers();</span><span style="color: #800080;">$user</span> = <span style="color: #800080;">$users</span>[0]; <span style="color: #008000;">//</span><span style="color: #008000;"> instance of ReadWriteRowGateway with a specific row of data from the db</span>

function是函数的意思,是一段具有特定功能的可重复使用的代码块,是程序的基本组成单元之一,可以接受输入参数,执行特定的操作,并返回结果,其目的是封装一段可重复使用的代码,提高代码的可重用性和可维护性。

每年Apple发布新的iOS和macOS大版本之前,用户都可以提前几个月下载测试版抢先体验一番。由于公众和开发人员都使用该软件,所以苹果公司为两者推出了developer和public版即开发者测试版的公共测试版。iOS的developer版和public版有什么区别呢?从字面上的意思来说,developer版是开发者测试版,public版是公共测试版。developer版和public版面向的对象不同。developer版是苹果公司给开发者测试使用的,需要苹果开发者帐号才可以收到下载并升级,是

在本文中,我们将了解enumerate()函数以及Python中“enumerate()”函数的用途。什么是enumerate()函数?Python的enumerate()函数接受数据集合作为参数并返回一个枚举对象。枚举对象以键值对的形式返回。key是每个item对应的索引,value是items。语法enumerate(iterable,start)参数iterable-传入的数据集合可以作为枚举对象返回,称为iterablestart-顾名思义,枚举对象的起始索引由start定义。如果我们忽

MySQL.proc表的作用和功能详解MySQL是一种流行的关系型数据库管理系统,开发者在使用MySQL时常常会涉及到存储过程(StoredProcedure)的创建和管理。而MySQL.proc表则是一个非常重要的系统表,它存储了数据库中所有的存储过程的相关信息,包括存储过程的名称、定义、参数等。在本文中,我们将详细解释MySQL.proc表的作用和功能

Vue.use函数的用法和作用Vue是一款流行的前端框架,它提供了许多有用的功能和功能。其中之一就是Vue.use函数,它可以让我们在Vue应用中使用插件。本文将介绍Vue.use函数的用法和作用,并且提供一些代码示例。Vue.use函数的基本用法非常简单,只需在Vue实例化之前调用它,并传入要使用的插件作为参数。下面是一个简单的示例://引入并使用插件

file_exists方法检查文件或目录是否存在。它接受要检查的文件或目录的路径作为参数。以下是它的用途-当您需要在处理之前知道文件是否存在时,它非常有用。这样,在创建新文件时使用此函数即可知道该文件是否已存在。语法file_exists($file_path)参数file_path-设置要检查是否存在的文件或目录的路径。必需。返回file_exists()方法返回。如果文件或目录存在,则返回TrueFalse,如果文件或目录不存在示例让我们看一个检查“candidate.txt”文件和即使文件

js函数function用法有:1、声明函数;2、调用函数;3、函数参数;4、函数返回值;5、匿名函数;6、函数作为参数;7、函数作用域;8、递归函数。

随着互联网的发展,SOA(面向服务的架构)已经成为了当今企业级系统中的一种重要的技术架构。SOA架构中的服务可以被重复使用、重组和扩展,同时还能够简化系统开发和维护的过程。PHP作为一种被广泛使用的Web编程语言,也提供了一些用于实现SOA的函数库。接下来,我们将详细介绍如何在PHP中使用SOA函数。一、SOA的基本概念SOA是一种分布式系统开发的思想和架构


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Atom編輯器mac版下載
最受歡迎的的開源編輯器