찾다
백엔드 개발PHP 튜토리얼 [php]Collection跟持久化工厂
[php]Collection跟持久化工厂 Jun 13, 2016 pm 12:35 PM
collectionfunctionmappernbsppublic

[php]Collection和持久化工厂

        Mapper类中的findById($id)可以从数据库中取出指定id的一条数据,映射成一个对象返回。很多时候我们需要返回一个数据集合(findAll),那我们就需要一种数据结构来保存这些数据,在需要时映射成对象。既然一条数据映射成一个对象,那么一个数据集合就需要一个对象集合。可以把数据集合和对象集合放在一个类中,这样就方便处理数据到对象的映射了。我们把这个类命名为Collection,为了能更好好的访问集合对象,Collection子类都实现了Iterator接口,使用foreach可以方便访问。

       Collection的类结构:

                                          

        \demo\mapper\Collection: 

namespace demo\mapper;

use demo\base\AppException;
use demo\domain\DomainObject;
use demo\mapper\Mapper;

abstract class Collection {
	// 保存数据库取出的行数据
	protected $raws;
	// 保存已映射的对象
	protected $objects = array();
	// 用于$raws[]到$objects的映射
	protected $mapper;
	// 当前指针
	private $pointer = 0;
	// 对象数组总数
	private $total = 0;
	
	/**
	 * @param array $raws 未处理过的数据库数据
	 * @param Mapper $mapper 用于把$raws映射成对象(createObject)
	 */
	public function __construct(array $raws = null, Mapper $mapper = null) {
		if (!is_null($raws) && !is_null($mapper)) {
			$this->raws = $raws;
			$this->total = count($raws);
		}
		
		$this->mapper = $mapper;
	}
	
	/**
	 * 返回指定$num的数据对象
	 * @param int $num
	 */
	public function getRow($num) {
		if ($num = $this->total) {
			return null;
		}
		
		// 延迟加载
		$this->notifyAccess();
		
		if (isset($this->objects[$num])) {
			return $this->objects[$num];
		}
		
		if (isset($this->raws[$num])) {
			$obj = $this->mapper->createObject($this->raws[$num]);
			$this->objects[$num] = $obj;
			return $obj;
		}
		
		return null;
	}
	
	/**
	 * 添加对象
	 * @param DomainObject $obj
	 * @throws AppException
	 */
	public function add(DomainObject $obj) {
		// 类型安全检查
		$targetClass = $this->getTargetClass();
		if (!($obj instanceof $targetClass)) {
			throw new AppException("Object must be {$targetClass}");
		}
		
		// 
		$this->notifyAccess();
		$this->objects[$this->pointer++] = $obj;
	}
	
	public function current() {
		return $this->getRow($this->pointer);
	}
	
	public function next() {
		$obj = $this->getRow($this->pointer);
		if (!is_null($obj)) {
			$this->pointer++;
		}
		
		return $obj;
	}
	
	public function key() {
		return $this->pointer;
	}
	
	public function rewind() {
		$this->pointer = 0;
	}
	
	public function valid() {
		return !is_null($this->current());
	}
	
	/**
	 * 延迟加载
	 */
	protected  function notifyAccess() {
		// 暂时留空
	}
	
	protected abstract function getTargetClass();
}

        \demo\domain:

namespace demo\domain;

use \demo\domain\DomainObject;

interface ClassroomCollection extends \Iterator {
	public function add(DomainObject $obj);
}

interface StudentCollection extends \Iterator {
	public function add(DomainObject $obj);
}

interface ScoreCollection extends \Iterator {
	public function add(DomainObject $obj);
}
        \demo\mapper:
namespace demo\mapper;

class ClassroomCollection extends Collection 
		implements \demo\domain\ClassroomCollection {
	
	protected function getTargetClass() {
		return '\demo\domain\Classroom';
	}
}

class StudentCollection extends Collection 
		implements \demo\domain\StudentCollection {
	
	protected function getTargetClass() {
		return '\demo\domain\Student';
	}
}

class ScoreCollection extends Collection 
		implements \demo\domain\ScoreCollection {

	protected function getTargetClass() {
		return '\demo\domain\Score';
	}
}
        为什么需要为domain包还需要一个Collection接口呢?因为domain包需要用到Collection来保存数据,为了让domain包不依赖于mapper包的Collection,所以创建了一个接口。而\demo\domain\mapper\Collection则会实现这个接口。

         现在的结构开始有点复杂了,为了能管理好Mapper和Collection的具体子类,我们可以使用抽象工厂来管理对象的创建。来看看类图:

                                           

        \demo\mapper\PersistanceFatory

namespace demo\mapper;

/**
 * 持久化工厂
 */
abstract class PersistanceFactory {
	
	public static function getFactory($targetClass) {
		switch ($targetClass) {
			case '\demo\domain\Classroom':
				return new ClassroomPersistanceFactory();
				
			case '\demo\domain\Student':
				return new StudentPersistanceFactory();
				
			case '\demo\domain\Score':
				return new ScorePersistanceFactory();
		}
	}
	
	public abstract function getMapper();
	
	public abstract function getCollection(array $raws = null);
}

class ClassroomPersistanceFactory extends PersistanceFactory {
	public function getMapper() {
		return new ClassroomMapper();
	}
	
	public function getCollection(array $raws = null) {
		return new ClassroomCollection($raws, $this->getMapper());
	}
}

class StudentPersistanceFactory extends PersistanceFactory {
	public function getMapper() {
		return new StudentMapper();
	}
	
	public function getCollection(array $raws = null) {
		return new StudentCollection($raws, $this->getMapper());
	}
}

class ScorePersistanceFactory extends PersistanceFactory {
	public function getMapper() {
		return new ScoreMapper();
	}
	
	public function getCollection(array $raws = null) {
		return new ScoreCollection($raws, $this->getMapper());
	}
}
        使用这样的工厂模式可以很方便地创建指定的Mapper和Collection子类了,同时这种方式也可以方便以后新功能的添加。

        domain包中同样需要Collection对象,但需要注意和mapper中的Collection分离开来。我们可以在domain包中创一个HelperFactory类来当做domain访问mapper的桥梁。

                                                              

namespace demo\domain;

use demo\mapper\PersistanceFactory;

class HelperFactory {
	
	public static function getCollection($targetClass) {
		$fact = PersistanceFactory::getFactory($targetClass);
		return $fact->getCollection();
	}
	
	public static function getFinder($targetClass) {
		$fact = PersistanceFactory::getFactory($targetClass);
		return $fact->getMapper();	
	}
}

        这样就把domain包和mapper包分离开来了。


       Collection有了,那么就来实现Mapper的findAll()吧。

namespace demo\mapper;

use demo\base\AppException;
use \demo\base\ApplicationRegistry;

/**
 * Mapper
 */
abstract  class Mapper {
	
	//...
	
	/**
	 * 返回Collection
	 */
	public function findAll() {
		$pStmt = $this->getSelectAllStmt();
		$pStmt->execute(array());
		$raws = $pStmt->fetchAll(\PDO::FETCH_ASSOC);
		$collection = $this->getCollection($raws);
		
		return $collection;
	}
	
	/**
	 * 返回子类Collection
	 * @param array $raw
	 */
	public function getCollection(array $raws) {
		return $this->getFactory()->getCollection($raws);
	}
	
	/**
	 * 返回子类持久化工厂对象
	 */
	public function getFactory() {
		return PersistanceFactory::getFactory($this->getTargetClass());		
	}
	
	//....
}

         例子:

$fact = PersistanceFactory::getFactory('\demo\domain\Classroom');
$mapper = $fact->getMapper();
$classrooms = $mapper->findAll();
foreach ($classrooms as $elem) {
	var_dump($elem);
}

        Colletion能方便管理$raws[]到$objects[]的映射。
        PersistanceFactory能管理好mapper包中类对象的创建。
        HelperFactory把mapper包和domain包分离开来。

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
解决方法:您的组织要求您更改 PIN 码解决方法:您的组织要求您更改 PIN 码Oct 04, 2023 pm 05:45 PM

“你的组织要求你更改PIN消息”将显示在登录屏幕上。当在使用基于组织的帐户设置的电脑上达到PIN过期限制时,就会发生这种情况,在该电脑上,他们可以控制个人设备。但是,如果您使用个人帐户设置了Windows,则理想情况下不应显示错误消息。虽然情况并非总是如此。大多数遇到错误的用户使用个人帐户报告。为什么我的组织要求我在Windows11上更改我的PIN?可能是您的帐户与组织相关联,您的主要方法应该是验证这一点。联系域管理员会有所帮助!此外,配置错误的本地策略设置或不正确的注册表项也可能导致错误。即

Windows 11 上调整窗口边框设置的方法:更改颜色和大小Windows 11 上调整窗口边框设置的方法:更改颜色和大小Sep 22, 2023 am 11:37 AM

Windows11将清新优雅的设计带到了最前沿;现代界面允许您个性化和更改最精细的细节,例如窗口边框。在本指南中,我们将讨论分步说明,以帮助您在Windows操作系统中创建反映您的风格的环境。如何更改窗口边框设置?按+打开“设置”应用。WindowsI转到个性化,然后单击颜色设置。颜色更改窗口边框设置窗口11“宽度=”643“高度=”500“>找到在标题栏和窗口边框上显示强调色选项,然后切换它旁边的开关。若要在“开始”菜单和任务栏上显示主题色,请打开“在开始”菜单和任务栏上显示主题

如何在 Windows 11 上更改标题栏颜色?如何在 Windows 11 上更改标题栏颜色?Sep 14, 2023 pm 03:33 PM

默认情况下,Windows11上的标题栏颜色取决于您选择的深色/浅色主题。但是,您可以将其更改为所需的任何颜色。在本指南中,我们将讨论三种方法的分步说明,以更改它并个性化您的桌面体验,使其具有视觉吸引力。是否可以更改活动和非活动窗口的标题栏颜色?是的,您可以使用“设置”应用更改活动窗口的标题栏颜色,也可以使用注册表编辑器更改非活动窗口的标题栏颜色。若要了解这些步骤,请转到下一部分。如何在Windows11中更改标题栏的颜色?1.使用“设置”应用按+打开设置窗口。WindowsI前往“个性化”,然

OOBELANGUAGE错误Windows 11 / 10修复中出现问题的问题OOBELANGUAGE错误Windows 11 / 10修复中出现问题的问题Jul 16, 2023 pm 03:29 PM

您是否在Windows安装程序页面上看到“出现问题”以及“OOBELANGUAGE”语句?Windows的安装有时会因此类错误而停止。OOBE表示开箱即用的体验。正如错误提示所表示的那样,这是与OOBE语言选择相关的问题。没有什么可担心的,你可以通过OOBE屏幕本身的漂亮注册表编辑来解决这个问题。快速修复–1.单击OOBE应用底部的“重试”按钮。这将继续进行该过程,而不会再打嗝。2.使用电源按钮强制关闭系统。系统重新启动后,OOBE应继续。3.断开系统与互联网的连接。在脱机模式下完成OOBE的所

Windows 11 上启用或禁用任务栏缩略图预览的方法Windows 11 上启用或禁用任务栏缩略图预览的方法Sep 15, 2023 pm 03:57 PM

任务栏缩略图可能很有趣,但它们也可能分散注意力或烦人。考虑到您将鼠标悬停在该区域的频率,您可能无意中关闭了重要窗口几次。另一个缺点是它使用更多的系统资源,因此,如果您一直在寻找一种提高资源效率的方法,我们将向您展示如何禁用它。不过,如果您的硬件规格可以处理它并且您喜欢预览版,则可以启用它。如何在Windows11中启用任务栏缩略图预览?1.使用“设置”应用点击键并单击设置。Windows单击系统,然后选择关于。点击高级系统设置。导航到“高级”选项卡,然后选择“性能”下的“设置”。在“视觉效果”选

Windows 11 上的显示缩放比例调整指南Windows 11 上的显示缩放比例调整指南Sep 19, 2023 pm 06:45 PM

在Windows11上的显示缩放方面,我们都有不同的偏好。有些人喜欢大图标,有些人喜欢小图标。但是,我们都同意拥有正确的缩放比例很重要。字体缩放不良或图像过度缩放可能是工作时真正的生产力杀手,因此您需要知道如何对其进行自定义以充分利用系统功能。自定义缩放的优点:对于难以阅读屏幕上的文本的人来说,这是一个有用的功能。它可以帮助您一次在屏幕上查看更多内容。您可以创建仅适用于某些监视器和应用程序的自定义扩展配置文件。可以帮助提高低端硬件的性能。它使您可以更好地控制屏幕上的内容。如何在Windows11

10种在 Windows 11 上调整亮度的方法10种在 Windows 11 上调整亮度的方法Dec 18, 2023 pm 02:21 PM

屏幕亮度是使用现代计算设备不可或缺的一部分,尤其是当您长时间注视屏幕时。它可以帮助您减轻眼睛疲劳,提高易读性,并轻松有效地查看内容。但是,根据您的设置,有时很难管理亮度,尤其是在具有新UI更改的Windows11上。如果您在调整亮度时遇到问题,以下是在Windows11上管理亮度的所有方法。如何在Windows11上更改亮度[10种方式解释]单显示器用户可以使用以下方法在Windows11上调整亮度。这包括使用单个显示器的台式机系统以及笔记本电脑。让我们开始吧。方法1:使用操作中心操作中心是访问

如何修复Windows服务器中的激活错误代码0xc004f069如何修复Windows服务器中的激活错误代码0xc004f069Jul 22, 2023 am 09:49 AM

Windows上的激活过程有时会突然转向显示包含此错误代码0xc004f069的错误消息。虽然激活过程已经联机,但一些运行WindowsServer的旧系统可能会遇到此问题。通过这些初步检查,如果这些检查不能帮助您激活系统,请跳转到主要解决方案以解决问题。解决方法–关闭错误消息和激活窗口。然后,重新启动计算机。再次从头开始重试Windows激活过程。修复1–从终端激活从cmd终端激活WindowsServerEdition系统。阶段–1检查Windows服务器版本您必须检查您使用的是哪种类型的W

See all articles

핫 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를 무료로 생성하십시오.

뜨거운 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

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

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구