设计php框架_自制PHP框架之设计模式

为什么要使用设计模式?

设计模式,我的理解是为了达到“可复用”这个目标,而设计的一套相互协作的类。

感兴趣的读者可以阅读《Design Patterns: Elements of Reusable Object-Oriented Software》,四位作者(Gang of Four)在书中列举了业界闻名的23种设计模式。

这里先介绍我们框架要涉及的三种设计模式。

单例模式(singleton)

单例模式可以保证一个类只有一个对象实例, 常用在数据库存取类,从而节省硬件资源的消耗。

这里,我们改写上一章节的MySQL类

class MySQL extends DB{

private static $instance=null;

public static function getInstance(){

if(self::$instance==null){

self::$instance=new MySQL();

}

return self::$instance;

}

public function MySQL(){

/*Config*/

$this->IP='*';

$this->ServerID='*';

$this->ServerPassword='*';

$this->DataBaseName='*';

/*End of Config*/

$this->connection=mysqli_connect($this->IP,$this->ServerID,$this->ServerPassword,$this->DataBaseName);

if(!$this->connection){

die('Could not connect'.$this->connection);

}

mysqli_query($this->connection,'set names utf8');

}

public function Execute($sql){

return mysqli_query($this->connection,$sql);

}

public function Query($sql){

$result=mysqli_query($this->connection,$sql);

$arr=array();

while($row=mysqli_fetch_array($result)){

$arr[]=$row;

}

return $arr;

}

public function Close(){

mysqli_close($this->connection);

}

}

这里要注意的是,如果实例化一个MySQL类,我们不再写

$db=new MySQL();

而是这样:

$db=MySQL::getInstance();

因为只有getInstance这个静态函数,才能保证只调用一次MySQL类的构造函数。

单例模式是很常用的设计模式,这里不再赘述。

外观模式(Facade)

因为命名空间的问题,外观模式可以保证一个类的诸多方法看似是“一个类提供的”,这里我们先设计一个简单的服务提供者类

class ServiceProvider{

public function Write($arg){

echo $arg;

}

}

这个类只有一个Write方法,就是把参数打印出来

然后定义一个Facade类

class Facade{

public static function getInstance($classname,$args){

return new $classname($args);

}

public static function getFacadeAccessor(){

//

}

public static function __callstatic($method,$args){

$instance=static::getInstance(static::getFacadeAccessor(),$args);

return call_user_func_array(array($instance,$method),$args);

}

}

要理解这个类,我们只要关注最后一个函数,就是__callstatic魔术方法。这个方法就是Facade类型对象或者其子类在调用他自身没有定义过的函数时,就会调用__callstatic方法,而这个方法最后调用了call_user_func_array函数,就是把任务交给提供这项服务的类去完成,同时完成参数的传递。

我们再写一个Facade子类

class MyFacade extends Facade{

public static function getFacadeAccessor(){

return ServiceProvider::class;

}

}

这里注意,子类实现了父类没有具体实现的getFacadeAccessor方法,这个方法就是要告诉父类的__callstatic方法:“我作为Facade,代表的是什么哪个类,任务就由他来实现吧”,从语法上看,只是返回了一个表示类名的字符串。所以父类起初并不知道它的子类都代表着什么“服务提供者类”,只有当子类的静态函数被调用后,因为子类没有该静态函数,所以父类的__callstatic方法被启动了。

抽象工厂(Factory)

我对抽象工厂有一个粗俗的理解:“对象与字符串的对应”,也就是用一个字符串就可以创造一个类的对象。这种做法主要用在两种情况下是很方便的:

1.类名不稳定,会在项目中频繁修改

类名修改,很多时候并不是设计者的“命名洁癖”或者“命名强迫症”导致的修改,而是在项目的不断迭代,发觉这个类设计的不合理。如果这个类用的不频繁,那么改个类名只要手工做一些小的修改即可,但是如果这个类通篇存在于代码之中(假如是数据库类),那修改工作量就大了,当然,我们也可以对代码文件使用“字符串替换”,但是假如一个PHP写成的项目,PHP文件有几十上百个,这也是不合理的事。

2.类的设计者并不是类的使用者

类的设计者和类的使用者不是同一个开发人员,那么记忆一个字符串或许比记忆一个类名要生动的多。我们都学过计算机网络原理,都知道记忆一个域名要比记忆一个IP地址要生动的多,这就是DNS解决的问题。

因为抽象工厂很多教材都有涉及,不再赘述,本文将介绍一下目前非常流行的服务容器。

我们希望整个工程项目中,DB类,Session类,FileSystem类“拿来即用”,不用每次繁琐的初始化,比如写$db=new DB(arg1,arg2);这类语句,也希望DB等类型的对象像一个“全局”变量一般,在整个程序运行期间,随时可以调用。

服务容器可以让调用DB等类型的程序员不用知道这个类太多的细节,甚至可以用一个字符串的别名来创建这样一个对象。

我们定义一个服务容器类

class Container{

public $bindings;

public function bind($abstract,$concrete){

$this->bindings[$abstract]=$concrete;

}

public function make($abstract,$parameters=[]){

return call_user_func_array($this->bindings[$abstract],$parameters);

}

}

可以把服务容器简单的看成一个全局变量,bind方法就是用关联数组把字符串和构造函数做绑定。

至此,有了服务容器,我们的Model类就要做修改了

class Model implements IModel{

public static $table;

public static $container;

public static $db;

public function __construct(){

self::$container=new Container();

self::$container->bind('db',function(){

return MySQL::getInstance();

});

self::$db=self::$container->make('db',[]);

}

public static function get($id){

return self::where('id',$id);

}

public static function where($condition,$value){

$sql=sprintf("select * from %s where %s='%s'",self::$table,$condition,$value);

return self::$db->Query($sql);

}

public static function all(){

$sql=sprintf("select * from %s",self::$table);

return self::$db->Query($sql);

}

}

观察上面代码,我们同时用了单例模式和服务容器。

总结:如果要做一个PHP框架,应该要做好代码的复用。设计模式一直是很多争论的焦点,“究竟该不该使用设计模式?”,本文开始,我也努力回避“过于纠结这个问题”,我认为,设计模式有其存在的价值,至少在具体项目中,确实在很多版本迭代中节省了工作量,提高工作效率,但是如果在一个小项目中为了“秀一下我会设计模式”而使用设计模式,就不合理了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/343372.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java将列表转换为数组,反之亦然

介绍: 在本文中, 我们将快速学习如何将Java List (例如ArrayList )转换为数组,反之亦然。 如果您希望总体上了解有关ArrayList的更多信息,请随时阅读我们有关Java ArrayLists的文章。 同时,让我…

工业交换机选择时需要注意什么?

工业以太网交换机是用于连接以太网的设备,应用十分广泛,主要应用于:煤矿安全、轨道交通、工厂自动化、水处理系统、城市安防等。现如今,市场上的工业交换机品牌厂家有很多,如何选购合适的以太网交换机是件令人困扰的事…

【渝粤教育】国家开放大学2018年秋季 0266-22T设计构成 参考试题

试卷编号:0272 座位号 2018—2019年度第一学期期末考试 创建小企业 试题 一、名词解释(每小题10分,共40分) 1.产品 商业模式 创业计划 市场定位 二、单项选择题(每小题3分,共30分,每小题只…

html如何与php,html页面怎么跟php文件连接

HTML页面调用PHP文件的方法是要通过JavaScript来实现,在生成静态页面时,可以根据数据库id给html页面生成一个对应的JavaScript文件来调用PHP文件。HTML页面调用PHP文件的方法是要通过JavaScript来实现,在生成静态页面时,可以根据数…

【渝粤教育】国家开放大学2018年秋季 0350-21T幼儿园课程论 参考试题

试题编号:0365 座位号 2018-2019 学年度第一学期期末考试 电子商务概论 试题 一、名词解释题: (每题5分,共20分) 1.网上问卷调研法: 2.社交网络营销: 银行卡线上支付: 第三方物流企业配送&am…

为使节构建控制平面的指南第3部分-特定于域的配置API

这是探索为Envoy Proxy构建控制平面的系列文章的第3部分。 在本博客系列中,我们将研究以下领域: 采用一种机制来动态更新Envoy的路由,服务发现和其他配置 确定哪些组件构成了控制平面,包括后备存储,服务发现API&…

工业交换机中:千兆级别和快速级别传输效率对比

目前市面上的工业交换机种类繁多,我们在采购工业交换机的时候,一般都是按照传输速率来进行挑选的。千兆工业交换机和快速以太网交换机都是传输速率比较快的工业交换机,那么,他们之间有哪些区别呢?接下来就由飞畅科技的…

《操作系统A》期末考试复习题——大题51-62(手写笔记)

51、如果限制为两道的多道程序系统中,有4个作业进入系统,其进入系统时刻、估计运行时间为下图所示。系统采用SJF作业调度算法,采用SRTF进程调度算法。作业进入系统时刻、估计运行时间如下: 作业 进入系统时刻 估计运行时间/min …

【渝粤教育】国家开放大学2018年秋季 0553-21T色彩 参考试题

编号:0557 座位号: 2018~2019学年度第一学期期末考试 广告设计与制作 试题 2019年1月 一、设计题1(每小题30分,共30分) 请将“九州四海”设计成毎字44cm左右的与文字意义有直接联系的变形创意广告字体。 要…

php 登录记住密码,php 记住密码自动登录

做网站的时候会碰到记住密码,下次自动登录,一周内免登陆,一个月内免登陆这种需求。这种功能一般通过cookie来实现的。用户在登陆的时候,如果选择了记住密码或者一周内免登陆等这个选项的时候,则在用户成功登陆操作完成…

java8 默认方法_如何不使用Java 8默认方法

java8 默认方法警告:一旦阅读,您将无法看不到它 我在上一篇博客文章中讨论了默认方法的多重继承,以及它们在编译和运行时的行为。 这周,我将研究如何使用默认方法进行真正的继承,实际上,默认方法并非为之设…

【渝粤教育】国家开放大学2018年秋季 0706-22T行政管理学导论 参考试题

科目编号:[0709] 座位号 2018-2019学年度第一学期期末考试 初级会计实务(一) 试题 2019年 1 月 一、单选题(本大题共10小题,每小题3分,共计30分) (★请考生务必将答案填入到下面对应…

工业以太网交换机的安装流程详解

工业以太网交换机是应用于工业控制领域的以太网交换机设备,所以设备的安装调试是很重要的一环,那么,我们在安装工业交换机的过程中需要注意什么呢?工业以太网交换机的安装流程是什么呢?接下来我们就跟随飞畅科技的小编…

【渝粤教育】国家开放大学2018年秋季 0734-22T出纳实务 参考试题

试卷代号:1021 劳动与社会保障法 试题 2019年1月 一、单项选择题(每小题1分,共10分。在每小题的四个备选答案 中,选出一个正确的答案,请将正确答案的序号填在括号内) 1.劳动者的劳动权利能力和…

带有Spring Security的OAuth 2.0快速指南

“我喜欢编写身份验证和授权代码。” 〜从来没有Java开发人员。 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证。 在构建Web应用程序时,必须进行身份验证和授权。 然而,正确地做…

工业以太网交换机在实际应用中的优势

相信大家对交换机应该都不陌生,交换机可以说应用于网络通信的各个方面,它极大的帮助我们提高了工作效率;但是一般我们会分为工业交换机和普通交换机,在实际应用当中,不同的环境和场合我们还是要有所区分的,…

php soap debug,php soap客户端调试实例

1,php soap客户端代码,如下:try {$client new SoapClient(null,array(location >http://localhost/oms07/index.php?rapi,uri >http://localhost/oms07));$results $client->__soapCall(getFailParts, array(startTime>2013-1…

【渝粤教育】国家开放大学2018年秋季 1167t环境水利学 参考试题

试卷代号:1189 政府经济学 试题 2019年1月 一、单项选择题(每小题1分,共10分) 1.政府经济的依据主要是( )。 A.私人财产所有权 B.社会公共权力 C.道德劝说 D.法律制度 2.公共选择的基本原理是将( )的分析方法用于非市场的政治领域…

php vimrc配置文件,vim技巧:我的 .vimrc 配置文件,详解每一个配置项的作用

下面是我的 .vimrc 配置文件,每一个配置项都添加了注释说明,详解每一个配置项的作用,以便确认为什么要添加这个配置项。" 使用vim的modeline来设置当前文件的textwidth,避免输入超过78个字符时自动换行" 使用:verbose set textwidt…

【渝粤教育】国家开放大学2018年秋季 1317T社会工作行政(本) 参考试题

试卷代号:1325 妇产科学与儿科护理学 试题 2019年1月 一、单项选择题(每题2分,共50分) 1.正常胎心率的范围是( )。 A. 80~100次/分 B.100~120次/分 C.120&…