백엔드 개발 PHP 튜토리얼 Constructor Prototype Pattern 原型模式(PHP示范)

Constructor Prototype Pattern 原型模式(PHP示范)

Jun 13, 2016 pm 12:25 PM
function public

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>
로그인 후 복사

 

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

기능은 무슨 뜻인가요? 기능은 무슨 뜻인가요? Aug 04, 2023 am 10:33 AM

함수는 특정 기능을 포함하는 재사용 가능한 코드 블록으로, 입력 매개변수를 받아들이고 특정 작업을 수행하며 결과를 반환하는 것이 목적입니다. 코드 재사용성과 유지 관리성을 향상시키는 코드입니다.

iOS 개발자 버전과 공개 버전의 차이점은 무엇인가요? iOS 개발자 버전과 공개 버전의 차이점은 무엇인가요? Mar 01, 2024 pm 12:55 PM

매년 Apple이 iOS 및 macOS의 새로운 주요 버전을 출시하기 전에 사용자는 몇 달 전에 베타 버전을 다운로드하여 먼저 경험할 수 있습니다. 소프트웨어는 대중과 개발자 모두가 사용하기 때문에 Apple은 개발자 베타 버전의 공개 베타 버전인 개발자 버전과 공개 버전을 모두 출시했습니다. iOS 개발자 버전과 공개 버전의 차이점은 무엇인가요? 말 그대로 개발자 버전은 개발자 베타 버전이고, 퍼블릭 버전은 퍼블릭 베타 버전이다. 개발자 버전과 공개 버전은 서로 다른 대상을 대상으로 합니다. 개발자 버전은 개발자가 테스트하기 위해 Apple에서 사용합니다. 다운로드하고 업그레이드하려면 Apple 개발자 계정이 필요합니다.

MySQL.proc 테이블의 역할과 기능에 대한 자세한 설명 MySQL.proc 테이블의 역할과 기능에 대한 자세한 설명 Mar 16, 2024 am 09:03 AM

MySQL.proc 테이블의 역할과 기능에 대한 자세한 설명 MySQL은 널리 사용되는 관계형 데이터베이스 관리 시스템으로, 개발자가 MySQL을 사용할 때 저장 프로시저(StoredProcedure)를 생성하고 관리하는 경우가 많습니다. MySQL.proc 테이블은 저장 프로시저의 이름, 정의, 매개변수 등을 포함하여 데이터베이스의 모든 저장 프로시저와 관련된 정보를 저장하는 매우 중요한 시스템 테이블입니다. 이번 글에서는 MySQL.proc 테이블의 역할과 기능에 대해 자세히 설명하겠습니다.

Python에서 'enumerate()' 함수의 목적은 무엇입니까? Python에서 'enumerate()' 함수의 목적은 무엇입니까? Sep 01, 2023 am 11:29 AM

이번 글에서는 enumerate() 함수와 Python에서 “enumerate()” 함수의 목적에 대해 알아봅니다. enumerate() 함수란 무엇입니까? Python의 enumerate() 함수는 데이터 컬렉션을 매개변수로 받아들이고 열거형 객체를 반환합니다. 열거형 객체는 키-값 쌍으로 반환됩니다. 키는 각 항목에 해당하는 인덱스이고 값은 항목입니다. 구문 enumerate(iterable,start) 매개변수 iterable - 전달된 데이터 컬렉션은 iterablestart라는 열거형 개체로 반환될 수 있습니다. - 이름에서 알 수 있듯이 열거형 개체의 시작 인덱스는 start로 정의됩니다. 우리가 무시한다면

Vue.use 함수의 사용법과 기능 Vue.use 함수의 사용법과 기능 Jul 24, 2023 pm 06:09 PM

Vue.use 함수의 사용법 및 기능 Vue는 많은 유용한 기능을 제공하는 널리 사용되는 프런트 엔드 프레임워크입니다. 그 중 하나는 Vue 애플리케이션에서 플러그인을 사용할 수 있게 해주는 Vue.use 기능입니다. 이 기사에서는 Vue.use 함수의 사용법과 기능을 소개하고 몇 가지 코드 예제를 제공합니다. Vue.use 함수의 기본 사용법은 매우 간단합니다. Vue가 인스턴스화되기 전에 호출하고 매개변수로 사용하려는 플러그인을 전달하면 됩니다. 다음은 간단한 예입니다. //플러그인 소개 및 사용

PHP의 file_exists() 함수 PHP의 file_exists() 함수 Sep 14, 2023 am 08:29 AM

file_exists 메소드는 파일이나 디렉토리가 존재하는지 확인합니다. 확인할 파일이나 디렉터리의 경로를 인수로 받아들입니다. 용도는 다음과 같습니다. 파일을 처리하기 전에 파일이 존재하는지 알아야 할 때 유용합니다. 이렇게 하면 새 파일을 만들 때 이 기능을 사용하여 파일이 이미 존재하는지 알 수 있습니다. 구문 file_exists($file_path) 매개변수 file_path - 존재 여부를 확인할 파일 또는 디렉터리의 경로를 설정합니다. 필수의. return file_exists() 메서드가 반환됩니다. 파일이나 디렉터리가 존재하면 TrueFalse를 반환하고, 파일이나 디렉터리가 존재하지 않으면 예를 들어 "candidate.txt" 파일을 확인하고 파일이

js 함수의 사용법은 무엇입니까 js 함수의 사용법은 무엇입니까 Oct 07, 2023 am 11:25 AM

js 함수 함수의 사용법은 다음과 같습니다. 1. 함수 호출 3. 함수 반환 값 6. 함수 범위 8.

PHP에서 SOA 함수를 사용하는 방법 PHP에서 SOA 함수를 사용하는 방법 May 18, 2023 pm 01:10 PM

인터넷의 발전과 함께 SOA(서비스 지향 아키텍처)는 오늘날의 기업 수준 시스템에서 중요한 기술 아키텍처가 되었습니다. SOA 아키텍처의 서비스는 재사용, 재구성 및 확장이 가능하며 시스템 개발 및 유지 관리 프로세스도 단순화됩니다. 널리 사용되는 웹 프로그래밍 언어인 PHP는 SOA 구현을 위한 일부 기능 라이브러리도 제공합니다. 다음으로 PHP에서 SOA 기능을 사용하는 방법을 자세히 설명하겠습니다. 1. SOA의 기본 개념은 분산 시스템 개발 아이디어와 아키텍처입니다.

See all articles