老生常谈PHP面向对象之标识映射


Posted in PHP onJune 21, 2017

标识映射在数据映射器的基础上增加了标识映射类,主要功能是保存已经创建好的对象,在需要的时候可以直接获取而不是重复创建造成系统性能的下降。

在数据映射器基础上还增加了部分调用标识映射类的方法,示例代码如下:

namespace woo\domain;

//标识映射类
class ObjectWatcher{
  
  private $all = array();        //存放对象的小仓库
  private static $instance;      //单例
  
  private function __construct (){}
  
  static function instance(){
    if(!self::$instance){
      self::$instance = new ObjectWatcher();
    }
    return self::$instance;
  }
  
  //获取一个唯一的标识,这里采用了领域类类名+ID的方式创建一个唯一标识,避免多个数据库表调用这个类时出现ID重复的问题
  function globalKey(DomainObject $obj){
    $key = get_class($obj) . "." . $obj->getId();
    return $key;
  }
  
  //添加对象
  static function add(DomainObject $obj){
    $inst = self::instance();
    $inst->all[$inst->globalKey($obj)] = $obj;
  }
  
  //获取对象
  static function exists($classname,$id){
    $inst = self::instance();
    $key = "$classname.$id";
    if(isset($inst->all[$key]){
      return $inst->all[$key];
    }
    return null;
  }
}

namespace woo\mapper;

abstract class Mapper{      //抽象基类
  abstract static $PDO;    //操作数据库的pdo对象
  function __construct (){
    if(!isset(self::$PDO){
      $dsn = \woo\base\ApplicationRegistry::getDSN();
      if(is_null($dsn)){
        throw new \woo\base\AppException("no dns");
      }
      self::$PDO = new \PDO($dsn);
      self::$PDO->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION);
    }
  }
  
  //数据映射器基础上新增的方法以下会简称新增,这里的作用的是获取对象而不是查询数据库并重复创建对象
  //(对比一下原数据映射器的相关代码即可了解)
  private function getFroMap($id){
    return \woo\domain\ObjectWatcher::exists($this->targetClass(),$id);
  }
  
  //新增,这里的作用的是将创建的对象保存起来
  private function addToMap(\woo\domain\DomainObject $obj){//////
    return \woo\domain\ObjectWatcher::add($obj);
  }
  
  
  //对比原数据映射器的代码,便发现它不是直接创建对象而是首先在标识映射类中查找,找不到才调用的
  //子类的方法创建并插入到标识映射类,下面的find方法也遵循了这一原则
  function createObject($array){          
    $old = $this->getFromMap($array['id']);  //新增
    if($old){return $old}          //新增
    $obj = $this->doCreateObject($array);  //在子类中实现
    $this->addToMap($obj);          //新增
    return $obj;
  }
  
  //
  function find($id){                //通过ID从数据库中获取一条数据并创建为对象  
    $old = $this->getFromMap($id);        //新增
    if($old){return $old}            //新增
    
    $this->selectStmt()->execute(array($id));
    $array= $this->selectStmt()->fetch();
    $this->selectStmt()->closeCursor();
    if(!is_array($array)){
      return null;
    }
    if(!isset($array['id'])){
      return null;
    }
    $object = $this->createObject($array);
    $this->addToMap($object);          //新增
    return $object;  
  }
  
  function insert(\woo\domain\DomainObject $obj){      //将对象数据插入数据库
    $this->doInsert($obj);
    $this->addToMap($obj);            //新增
  }
  
  //需要在子类中实现的各抽象方法
  abstract function targetClass();//////
  abstract function update(\woo\domain\DomainObject $objet);
  protected abstract function doCreateObject(array $array);
  protected abstract function selectStmt();
  protected abstract function doInsert(\woo\domain\DomainObject $object);
}

class SpaceMapper extends Mapper {
  //其他代码在数据映射器一文中已有实现这里略过
  //.............
  
  //类名,在标识映射类中生成唯一标识用的
  protected function targetClass(){
    return "woo\\domain\\Space";
  }
}

以上这篇老生常谈PHP面向对象之标识映射就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
用Php实现链结人气统计
Oct 09 PHP
谷歌音乐搜索栏的提示功能php修正代码
May 09 PHP
PHP中空字符串介绍0、null、empty和false之间的关系
Sep 25 PHP
解析PHP中empty is_null和isset的测试
Jun 29 PHP
浅谈web上存漏洞及原理分析、防范方法(文件名检测漏洞)
Jun 29 PHP
php curl获取网页内容(IPV6下超时)的解决办法
Jul 16 PHP
thinkphp的c方法使用示例
Feb 24 PHP
Codeigniter操作数据库表的优化写法总结
Jun 12 PHP
php+ajax实现无刷新数据分页的办法
Nov 02 PHP
WordPress特定文章对搜索引擎隐藏或只允许搜索引擎查看
Dec 31 PHP
PHP实现根据时间戳获取周几的方法
Feb 26 PHP
thinkPHP5框架中widget的功能与用法详解
Jun 11 PHP
PHP封装的PDO数据库操作类实例
Jun 21 #PHP
PHP基于ORM方式操作MySQL数据库实例
Jun 21 #PHP
php 猴子摘桃的算法
Jun 20 #PHP
详解php框架Yaf路由重写
Jun 20 #PHP
PHP简单计算两个时间差的方法示例
Jun 20 #PHP
php实现的错误处理封装类实例
Jun 20 #PHP
PHP实现在windows下配置sendmail并通过mail()函数发送邮件的方法
Jun 20 #PHP
You might like
50个优秀经典PHP算法大集合 附源码
2020/08/26 PHP
javascript实现日历控件(年月日关闭按钮)
2012/12/12 Javascript
原生Js页面滚动延迟加载图片实现原理及过程
2013/06/24 Javascript
js计算两个时间之间天数差的实例代码
2013/11/19 Javascript
javascript中数组array及string的方法总结
2014/11/28 Javascript
JavaScript运算符小结
2015/06/03 Javascript
JavaScript正则表达式之multiline属性的应用
2015/06/16 Javascript
jquery实现手机号码选号的方法
2015/07/31 Javascript
Bootstrap实现水平排列的表单
2016/07/04 Javascript
JQuery Ajax 异步操作之动态添加节点功能
2017/05/24 jQuery
angular实现spa单页面应用实例
2017/07/10 Javascript
浅谈angular2 组件的生命周期钩子
2017/08/12 Javascript
JavaScript设计模式之调停者模式实例详解
2018/02/03 Javascript
实用的 vue tags 创建缓存导航的过程实现
2020/12/03 Vue.js
Java 生成随机字符的示例代码
2021/01/13 Javascript
python远程登录代码
2008/04/29 Python
Python求两个list的差集、交集与并集的方法
2014/11/01 Python
Python机器学习之决策树算法实例详解
2017/12/06 Python
Python输入二维数组方法
2018/04/13 Python
python里 super类的工作原理详解
2019/06/19 Python
使用Python的Turtle绘制哆啦A梦实例
2019/11/21 Python
Tensorflow获取张量Tensor的具体维数实例
2020/01/19 Python
如何在网站上添加谷歌定位信息
2016/04/16 HTML / CSS
html5简介及新增功能介绍
2020/05/18 HTML / CSS
Europcar美国/加拿大:预订汽车或卡车租赁服务
2018/11/13 全球购物
计算机应用专业学生的自我评价分享
2013/11/03 职场文书
英语专业学生个人求职信范文
2014/01/06 职场文书
新年抽奖获奖感言
2014/03/02 职场文书
学生考试舞弊检讨书
2015/01/01 职场文书
销售经理工作检讨书
2015/02/19 职场文书
大学四年个人总结
2015/03/03 职场文书
我在伊朗长大观后感
2015/06/16 职场文书
Python一行代码实现自动发邮件功能
2021/05/30 Python
基于JavaScript实现省市联动效果
2021/06/22 Javascript
Windows server 2012 R2 安装IIS服务器
2022/04/29 Servers
python pygame 开发五子棋双人对弈
2022/05/02 Python