PHP设计模式之:注册模式入门教程
当你有一组全局对象被全局访问时可能就需要用到注册模式 (registry),它提供了在程序中有条理的存放并管理对象 (object)一种解决方案。一个“注册模式”应该提供get() 和 set()方法来存储和取得对象。
注册模式通过单一的全局的对象来获取对其它对象的引用 实例:
<?php /** * PHP设计模式之注册模式实例 * */ class Registry { protected static $objects; //用于存放对象的数组 /** * 将对象放到对象数组上 * @param string $alias 别名 * @param object $object 对象 */ static function set($alias, $object) { self::$objects[$alias] = $object; } /** * 将对象从数组上删除 * @param string $alias 别名 */ static function _unset($alias) { unset(self::$objects[$alias]); } /** * 通过别名获取对象 * @param string $alias 别名 */ static function get($alias) { if (array_key_exists($alias, self::$objects)) { return self::$objects[$alias]; } } } class MyObject { public function test(){ return 'ok'; } } //结合工厂模式 class MyFactory { public static function factory(){ //返回对象的实例 $myObject = new MyObject(); Registry::set("myObject", $myObject); } } //调用工厂 MyFactory::factory(); //使用 echo Registry::get("myObject")->test(); Registry::_unset("myObject"); ?>
好了,PHP的三种基础模式已经介绍完了,随后博主会继续学习分享PHP的其他设计模式,谢谢!
单例模式小编讲过非常的多了,今天小编看到一个朋友分享的一篇单例模式了,下面我们一起来看看,希望文章能够对各位带来帮助。
博主最近开始真正的潜心学习PHP的各种设计模式。刚开始当然从一些简单的设计模式开始学起,比如之前发表的工厂模式,今天的单利模式,还有之后要看的注册模式。其实这些都是比较基础的设计模式,一些简单的示例一看就能明白,对于稍加复杂些的示例,花点心思进去也能够理解。可重点是,光是知道了解这么个东西是不够的,而是如何能够把他更好的运用的项目中去,在实践中增加熟练度。好吧,还是说说今天要看的单例模式吧。
一、什么是单例模式?
1、含义:
作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统全局地提供这个实例。它不会创建实例副本,而是会向单例类内部存储的实例返回一个引用。
2、单例模式的三个要点:
(1)需要一个保存类的唯一实例的静态成员变量。
(2)构造函数和克隆函数必须声明为私有的,防止外部程序new类从而失去单例模式的意义。
(3)必须提供一个访问这个实例的公共的静态方法(通常为getInstance方法),从而返回唯一实例的一个引用。
假设我们目前需要设计一个数据库访问类,需要用到单例模式,看如下示例:
<?php class DB { private $_db; private static $_instance; private function __construct(...) { $this->_db = pg_connect(...);//postgrsql } private function __clone() {}; //覆盖__clone()方法,禁止克隆 public static function getInstance() { if(!(self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; } public function sql(...) { /* * code */ } } $db = DB::getInstance(); $db->sql(); ?>
<111?111php111
/1**
* 设计模式之单例模式
* $_instance必须声明为静态的私有变量
* 构造函数和析构函数必须声明为私有,防止外部程序new
* 类从而失去单例模式的意义
* getInstance()方法必须设置为公有的,必须调用此方法
* 以返回实例的一个引用
* ::操作符只能访问静态变量和静态函数
* new对象都会消耗内存
* 使用场景:最常用的地方是数据库连接。
* 使用单例模式生成一个对象后,
* 该对象可以被其它众多对象所使用。
*/
class Danli {
//保存类实例的静态成员变量
private static $_instance;
//private标记的构造方法
private function __construct(){
echo 'This is a Constructed method;';
}
//创建__clone方法防止对象被复制克隆
public function __clone(){
trigger_error('Clone is not allow!',E_USER_ERROR);
}
//单例方法,用于访问实例的公共的静态方法
public static function getInstance(){
if(!(self::$_instance instanceof self)){
self::$_instance = new self;
}
return self::$_instance;
}
public function test(){
echo '调用方法成功';
}
}
//用new实例化private标记构造函数的类会报错
//$danli = new Danli();
//正确方法,用双冒号::操作符访问静态方法获取实例
$danli = Danli::getInstance();
$danli->test();
//复制(克隆)对象将导致一个E_USER_ERROR
$danli_clone = clone $danli;
例子3
1、普通的数据库访问例子:
<?php ...... //初始化一个数据库句柄 $db = new DB(...); //添加用户信息 $db->addUserInfo(...); ...... //在函数中访问数据库,查找用户信息 function getUserInfo() { $db = new DB(...);//再次new 数据库类,和数据库建立连接 $db = query(....);//根据查询语句访问数据库 } ?>
例子4、应用单例模式对数据库进行操作:
<?php class DB { private $_db; private static $_instance; private function __construct(...) { $this->_db = pg_connect(...);//postgrsql } private function __clone() {}; //覆盖__clone()方法,禁止克隆 public static function getInstance() { if(! (self::$_instance instanceof self) ) { self::$_instance = new self(); } return self::$_instance; } public function addUserInfo(...) { } public function getUserInfo(...) { } } //test $db = DB::getInstance(); $db->addUserInfo(...); $db->getUserInfo(...); ?>
二、为什么要使用单例模式?
1、PHP缺点:
PHP语言是一种解释型的脚本语言,这种运行机制使得每个PHP页面被解释执行后,所有的相关资源都会被回收。也就是说,PHP在语言级别上没有办法让某个对象常驻内存,这和asp.net、Java等编译型是不同的,比如在Java中单例会一直存在于整个应用程序的生命周期里,变量是跨页面级的,真正可以做到这个实例在应用程序生命周期中的唯一性。然而在PHP中,所有的变量无论是全局变量还是类的静态成员,都是页面级的,每次页面被执行时,都会重新建立新的对象,都会在页面执行完毕后被清空,这样似乎PHP单例模式就没有什么意义了,所以PHP单例模式我觉得只是针对单次页面级请求时出现多个应用场景并需要共享同一对象资源时是非常有意义的。
2、单例模式在PHP中的应用场合:
(1)应用程序与数据库交互
一个应用中会存在大量的数据库操作,比如过数据库句柄来连接数据库这一行为,使用单例模式可以避免大量的new操作,因为每一次new操作都会消耗内存资源和系统资源。
(2)控制配置信息
如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现.
适配器模式是php设计模式中的一个常用的模式了,很多朋友对于这个适配器模式不了解,下面小编和各位介绍一下吧,希望对大家帮助
适配器模式有什么用?
将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原来由于接口不兼容而不能一起工作的那此类可以一起工作
适用性
1、你想使用一个已经存在的类,而它的接口不符合你的需求
2、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类协同工作
3、你想使用一个已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口(仅限于对象适配器)
应用举例,例如PHP的数据库操作有MySQL、Mssql、PDO等,可以用适配器模式统一成一致。类似的场景还有cache适配器,将memcache、redis、file、apc等不同的缓存函数,统一成一致。
接下来我们以数据库操作来举例,为了编辑方便,博主就把代码都写一起了
<?php /** * PHP设计模式之适配器模式实例 * */ /** * 目标角色 * 创建一个接口文件 DataBase.php * 定义一个数据库接口 * 声明方法 */ interface IDataBase { public function connect($host, $user, $passwd, $dbname); public function query($sql); public function close(); } /** * 源角色 */ class Adaptee { /** * 源类含有的方法 */ public function connect($host, $user, $passwd, $dbname) { return 'Adaptee'; } } /** * 类适配器角色 * 创建mysql操作类文件 Mysql.php * 继承接口 实现接口方法 */ class Mysql implements IDataBase { private $_adaptee; function __construct() { $this->_adaptee = new Adaptee(); } public function connect($host, $user, $passwd, $dbname){ /** * code... * 委派调用Adaptee的connect方法 */ $this->_adaptee->connect($host, $user, $passwd, $dbname); //return 'ok'; } public function query($sql){ /** * code... */ return 'ok'; } public function close(){ /** * code... */ return 'ok'; } } /** * 类适配器角色 * 创建mssql操作类文件 Mssql.php * 继承接口 实现接口方法 */ class Mssql implements IDataBase { public function connect($host, $user, $passwd, $dbname){ /** * code... */ return 'ok'; } public function query($sql){ /** * code... */ return 'ok'; } public function close(){ /** * code... */ return 'ok'; } } /** * 类适配器角色 * 创建pdo操作类文件 Pdo.php * 继承接口 实现接口方法 */ class Pdfo implements IDataBase { public function connect($host, $user, $passwd, $dbname){ /** * code... */ return 'ok'; } public function query($sql){ /** * code... */ return 'ok'; } public function close(){ /** * code... */ return 'ok'; } } /** * 使用 * 这样就可以任意的在三种适配器之间进行切换 */ $db = new Mysql(); echo $db->connect('127.0.0.1', 'root', 'root', 'test'); echo $db->query('show databases'); echo $db->close(); ?>
博主也参考了网上一些示例,总觉得写的也不明确,直到写完这篇,博主依旧疑惑。不知道我的理解是否正确,看过之后的朋友还望指点一二。
好了,今儿就到这,更多深入信息可以自己去网上找,或者查看相关书籍
php中的设计模式中有很多的各种模式了,在这里我们来为各位介绍一个不常用的数据映射模式吧,希望文章能够帮助到各位。
之前的几种设计模式,都是大大提高了PHP代码的可读性、可维护性。但是,在WEB应用中还有更重要的需求与挑战,那就是:数据库应用。可之前的设计模式,都没有涉及于此。今天写到的,数据映射模式就是能够更好的组织应用程序与数据库进行交互。
博主这两天也是花了点时间对,这种模式有了那么一点的了解。斗胆在这个里献丑,按照自己的理解,写一点东西与大家分享,互相学习。
当然说到数据映射模式,就不得不提到对象关系映射(Object Relational Mapping,简称ORM),用于实现面向对象编程语言里不同类型系统的数据之间的转换。一般ORM框架对付简单的应用系统来说都能满足基本需求,可以大大降低开发难度,提高开发效率,但是它在SQL优化方面,肯定是比纯SQL语言要差很多,对复杂关联、SQL内嵌表达式的处理都不是很理想。
对于博主目前使用的TP框架,其核心文件Model.class.php就是实现了ORM和ActiveRecords模式,在项目中所有的模型也都是继承这个模型类。
好吧,还是不丢人说这些废话了,自己参考编写整理了一份实例,给大家分享一下,互相交流。
首先我们需要一个数据库中间层实现类,使用pdo进行数据库访问。当然这个类不是今天的重点,我也是从网上拷来的,可以直接忽略。
创建一个DB类文件 Db.class.php
<?php /* * 数据库中间层实现类 */ class Db { public static $db = null; private $_dbh = null; public static function getInstance() { if( self::$db == null ){ self::$db = new self(BACKEND_DBHOST ,BACKEND_DBUSER ,BACKEND_DBPW ,BACKEND_DBNAME); } return self::$db; } private function __construct( $host ,$user ,$pass ,$dbname ){ try { $this->_dbh = new PDO('mysql:dbname='.$dbname.';host='.$host,$user,$pass); $this->_dbh->query('SET NAMES '. BACKEND_DBCHARSET); $this->_dbh->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); $this->_dbh->setAttribute(PDO::ATTR_ERRMODE, true); } catch (PDOException $e) { throw new Exception('Can not connect db'); } } public function getOne($sql){ try { $rs = $this->_dbh->query($sql); $result = $rs->fetch(PDO::FETCH_ASSOC); if(!empty($result)) { return $result; } } catch (PDOException $e) { throw new Exception($this->_dbh->errorInfo()); } return false; } public function getAll($sql){ try { $rs = $this->_dbh->query($sql); $result = $rs->fetchAll(PDO::FETCH_ASSOC); if(!empty($result)) { return $result; } } catch (PDOException $e) { throw new Exception($this->_dbh->errorInfo()); } return false; } public function exec($sql){ try { $exec = $this->_dbh->exec($sql); } catch (PDOException $e){ throw new Exception($this->_dbh->errorInfo()); } return $exec; } public function getLastId() { return $this->_dbh->lastInsertId(); } } ?>
数据映射类 Table.class.php
<?php /** * 数据映射类 * 部分代码来源TP框架 * 使用相关魔术方法 则映射的表修改字段后无需修改属性值 */ class Table{ // 数据信息 protected $data = array(); // 数据信息 protected $db = null; // 表信息 protected $tableName = ''; public function __construct() { $this->db = Db::getInstance(); } /** * 设置数据对象的值 */ public function __set($name,$value) { // 设置数据对象属性 $this->data[$name] = $value; } /** * 获取数据对象的值 */ public function __get($name) { return isset($this->data[$name])?$this->data[$name]:null; } /* * 添加 * 修改、删除也和添加类似,就不一一列举了 */ public function add() { $data = $this->data; foreach($data as $k=>$v) { $fieldArr[] = $k; $valueArr[] = "'".$v."'"; } $fields = implode(',', $fieldArr); $values = implode(',', $valueArr); $sql = 'INSERT INTO '.$this->tableName.' ('.$fields.') VALUES ('.$values.')'; $result = $this->db->exec($sql); if($result) { return $this->db->getLastId(); } else { return false; } } } ?>
表对应的类文件 UserTable.class.php
<?php /** * 数据映射到表 * 一般根据表的结构由工具自动生成,比如Yii框架等。 */ class UserTable extends Table { protected $tableName = 'user'; } ?> 使用方式 index.php <?php /** * 数据库配置文件 */ define('BACKEND_DBHOST', 'localhost'); define('BACKEND_DBUSER', 'root'); define('BACKEND_DBPW', ''); define('BACKEND_DBNAME', 'test'); define('BACKEND_DBCHARSET', 'utf-8'); /* * 这里实例化对象时可以使用之前介绍的工厂模式和注册模式,来实例化和管理实例化对象 * TP框架中的D方法就是做了这部分工作 */ $UserTable = new UserTable(); $UserTable->username = 'Anrai'; $UserTable->mobile = '123456789'; $UserTable->email = 'huanglei.web@gmail.com'; echo $UserTable->add(); /* 数据表sql CREATE TABLE `user` ( `uid` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(30) NOT NULL, `mobile` varchar(11) NOT NULL DEFAULT '0', `email` varchar(60) NOT NULL DEFAULT '0', PRIMARY KEY (`uid`), KEY `username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 */ ?>设计模式中的观察者模式我相信很多php开发者都不是很了解了,下面一聚教程小编来为各位整理了一篇相关的文章供各位参考。
一些面向对象的编程方式,提供了一种构建对象间复杂网络互连的能力。当对象们连接在一起时,它们就可以相互提供服务和信息。这个模式对于大型系统项目来说应该是挺挺有用的,通俗的讲,这种模式允许某个类去观察另一个类。当一个类被改变时,观察类就会收到通知并且做出相应的动作。
在平时的项目中还是挺有用的,比如一个用户下了一笔订单,下单成功后,就需要去发送短信/邮件的通知,库存的修改,账户余额的修改等等很多操作。
在之后的PHP5.0起,内置的SPL标准库中就提供了这种设计模式接口供大家使用,接下了就通过实例来学习一下。
SPL 提供了 SplSubject 和 SplObserver 接口。
SplSubject 接口提供了attach()、detach()、notify() 三个方法。而 SplObserver 接口则提供了 update()方法。
<?php /** * 这一模式的概念是SplSubject类维护了一个特定状态,当这个状态发生变化时,它就会调用notify()方法。 * 调用notify()方法时,所有之前使用attach()方法注册的SplObserver实例的update方法都会被调用。 * */ interface SplSubject{ public function attach(SplObserver $observer);//注册观察者 public function detach(SplObserver $observer);//释放观察者 public function notify();//通知所有注册的观察者 } interface SplObserver{ public function update(SplSubject $subject);//观察者进行更新状态 } ?>
使用所提供的接口,来实现观察者模式
<?php /** *具体目标 */ class Salary implements SplSubject { private $observers, $money; public function __construct() { $this->observers = array(); } public function attach(SplObserver $observer) { //注册观察者 $this->observers[] = $observer; } public function detach(SplObserver $observer) { //释放观察者 if($idx = array_search($observer,$this->observers,true)) { unset($this->observers[$idx]); } } public function notify() { //通知所有观察者 foreach($this->observers as $observer) { $observer->update($this); } } public function payoff($money) { //发工资方法 $this->money = $money; $this->notify(); //通知观察者 } } /** * 具体观察者 */ class Programmer1 implements SplObserver { public function update(SplSubject $subject) { echo 'Programmer1 发工资了!<br/>'; } } class Programmer2 implements SplObserver { public function update(SplSubject $subject) { echo 'Programmer2 也发工资了!<br/>'; } } $subject = new Salary(); $observer1 = new Programmer1(); $observer2 = new Programmer2(); //注册观察者 $subject->attach($observer1); $subject->attach($observer2); //发工资操作,发起通知 $subject->payoff('20K'); ?>
通过Observer模式,把一对多对象之间的通知依赖关系的变得更为松散,大大地提高了程序的可维护性和可扩展性,也很好的符合了开放-封闭原则。东西是不错,如何能够更好的去使用它,仍需要多加实践、联系。
相关文章
- 神马是“解释器模式”?先翻开《GOF》看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如...2014-06-07
- 这篇文章主要为大家介绍了JavaScript设计模式中的装饰者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 这篇文章主要给大家介绍的是关于Lua语言新手入门的简单教程,文中通过示例代码一步步介绍的非常详细,对各位新手们的入门提供了一个很方便的教程,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。...2020-06-30
- 这篇文章主要介绍了JavaScript设计模式之职责链模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
- 这篇文章主要介绍了C#线程入门教程之单线程介绍,本文讲解了什么是进程、什么是线程、什么是多线程等内容,并给出了一个单线程代码示例,需要的朋友可以参考下...2020-06-25
- 这篇文章主要为大家介绍了JavaScript设计模式中的状态模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-12
- 这篇文章主要为大家介绍了JavaScript设计模式中的单例模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 这篇文章主要介绍了CocosCreator入门教程之用TS制作第一个游戏,对TypeScript感兴趣的同学,一定要看一下...2021-04-16
- 这篇文章主要介绍了JavaScript设计模式之命令模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
- 这篇文章主要为大家介绍了JavaScript设计模式中的责任链模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 这篇文章主要为大家介绍了JavaScript设计模式中的状态模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-14
- 这里主要讲到关于在php教程类的调用,申请明,使用以前各种类的实例方法与操作过程,让你清楚的知道php类的construct destruct clone call wake sleep用法。 简单购物车...2016-11-25
- 这篇文章主要为大家介绍了JavaScript设计模式中的观察者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 这篇文章主要给大家介绍的是JavaScript中的单例模式,设计模式代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案,需要的朋友可以参考一下...2021-09-25
- 下面举一个很简单的?表达式的实现吧,其实它就是简单的if else哦。 <? $a = 5; //定义变数a=5 $b = 3; //定义变数b=5 $c = ($a==$b) ? ("yes") : ("no"); //如果...2016-11-25
- 组合模式可以使客户端调用简单,它可以一致使用组合结构或是其中单个对象,简化了客户端代码。...2020-06-25
- 现在最热门的前端框架有AngularJS、React、Bootstrap等。自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领略ReactJs的风采吧~~ 文章有点长,耐心读完,你会有很大收获哦...2021-04-05
- php入门教程:php rtrim()实例教程 定义和用法 该rtrim ( )函数将删除空格或其他预先确定的性质从右侧的一个字符串。 语法 rtrim(string,charlist) 参数说明 字符...2016-11-25
- 这篇文章主要介绍了Golang极简入门教程(一):基本概念,本文讲解了Golang的基本知识、基础语法、相关术语等,需要的朋友可以参考下...2020-05-01
- 这篇文章主要介绍了Golang极简入门教程(三):并发支持,本文讲解了goroutine线程、channel 操作符等内容,需要的朋友可以参考下...2020-05-01