php基础设计模式大全(注册树模式、工厂模式、单列模式)


Posted in PHP onAugust 31, 2015

废话不多说了,先给大家介绍注册树模式然后介绍工厂模式最后给大家介绍单列模式,本文写的很详细,一起来学习吧。

php注册树模式

什么是注册树模式?

注册树模式当然也叫注册模式,注册器模式。之所以我在这里矫情一下它的名称,是因为我感觉注册树这个名称更容易让人理解。像前两篇一样,我们这篇依旧是从名字入手。注册树模式通过将对象实例注册到一棵全局的对象树上,需要的时候从对象树上采摘的模式设计方法。   这让我想起了小时候买糖葫芦,卖糖葫芦的将糖葫芦插在一个大的杆子上,人们买的时候就取下来。不同的是,注册树模式摘下来还会有,能摘很多次,糖葫芦摘一次就没了。。。

为什么要采用注册树模式?

单例模式解决的是如何在整个项目中创建唯一对象实例的问题,工厂模式解决的是如何不通过new建立实例对象的方法。 那么注册树模式想解决什么问题呢? 在考虑这个问题前,我们还是有必要考虑下前两种模式目前面临的局限。  首先,单例模式创建唯一对象的过程本身还有一种判断,即判断对象是否存在。存在则返回对象,不存在则创建对象并返回。 每次创建实例对象都要存在这么一层判断。 工厂模式更多考虑的是扩展维护的问题。 总的来说,单例模式和工厂模式可以产生更加合理的对象。怎么方便调用这些对象呢?而且在项目内如此建立的对象好像散兵游勇一样,不便统筹管理安排啊。因而,注册树模式应运而生。不管你是通过单例模式还是工厂模式还是二者结合生成的对象,都统统给我“插到”注册树上。我用某个对象的时候,直接从注册树上取一下就好。这和我们使用全局变量一样的方便实用。 而且注册树模式还为其他模式提供了一种非常好的想法。

如何实现注册树?

通过上述的描述,我们似乎很容易就找到了解决方法。首先我们需要一个作为注册树的类,这毋庸置疑。所有的对象“插入”到注册树上。这个注册树应该由一个静态变量来充当。而且这个注册树应该是一个二维数组。这个类应该有一个插入对象实例的方法(set()),当让相对应的就应该有一个撤销对象实例的方法(_unset())。当然最重要的是还需要有一个读取对象的方法(get())。拥有这些,我们就可以愉快地完成注册树模式啦~~~

下面让三种模式做个小小的结合。单纯创建一个实例对象远远没有这么复杂,但运用于大型项目的话,便利性便不言而喻了。

<?php
//创建单例
class Single{
 public $hash;
 static protected $ins=null;
 final protected function __construct(){
  $this->hash=rand(1,9999);
 }
 static public function getInstance(){
  if (self::$ins instanceof self) {
   return self::$ins;
  }
  self::$ins=new self();
  return self::$ins;
 } 
}
//工厂模式
class RandFactory{
 public static function factory(){
  return Single::getInstance();
 }
}
//注册树
class Register{
 protected static $objects;
 public static function set($alias,$object){
  self::$objects[$alias]=$object;
 }
 public static function get($alias){
  return self::$objects[$alias];
 }
 public static function _unset($alias){
  unset(self::$objects[$alias]);
 }
}
Register::set('rand',RandFactory::factory());
$object=Register::get('rand');
print_r($object);

       至此,三种模式设计介绍完毕。各种模式设计本身就会相辅相成,往后介绍其他模式的时候,多多少少会用到一种或多种其他设计模式。

   一种模式不懂不要紧,相信编程的深入,定会产生恍然大悟的惊喜感 ,愿诸君与我共进步。

php工厂模式

那么何为工厂模式?

从名字来看,似乎看不出什么端倪。工厂模式,和生产有关?还是和生产流程有关?难道还和工厂领导有关?和领导秘书有关?秘书...     好了不卖关子了,所谓工厂模式还真和生产有关。生产什么呢?生产出来的是一个实例对象。通过什么设备生产?通过一个工厂类生产。怎么生产呢?工厂类调用自身静态方法来生产对象实例。

   工厂模式有一个关键的构造,根据一般原则命名为Factory的静态方法,然而这只是一种原则,虽然工厂方法可以任意命名这个静态还可以接受任意数据的参数,必须返回一个对象。

为什么要是用工厂模式?

很多没接触过工厂模式的人会不禁问,为啥我要费那么大的劲儿去构造工厂类去创建对象呢?不去套用那些易维护,可扩展之类的话,我们可以考虑这样一个简单的问题。如果项目中,我们通过一个类创建对象。在快完成或者已经完成,要扩展功能的时候,发现原来的类类名不是很合适或者发现类需要添加构造函数参数才能实现功能扩展。我靠!我都通过这个类创建了一大堆对象实例了啊,难道我还要一个一个去改不成?我们现在才感受到了“高内聚低耦合”的博大精深。没问题,工厂方法可以解决这个问题。

再考虑一下,我要连接数据库,在php里面就有好几种方法,mysql扩展,mysqli扩展,PDO扩展。我就是想要一个对象用来以后的操作,具体要哪个,视情况而定喽。既然你们都是连接数据库的操作,你们就应该拥有相同的功能,建立连接,查询,断开连接...(此处显示接口的重要性)。总而言之,这几种方法应该“团结一致,一致对外”。如何实现呢?利用工厂模式。

工厂模式如何实现?

相对于单例模式,上面我们提供了足够的信息,工厂类,工厂类里面的静态方法。静态方法里面new一下需要创建的对象实例就搞定了。当然至于考虑上面的第二个问题,根据工厂类静态方法的参数,我们简单做个判断就好了。管你用if..else..还是switch..case..,能快速高效完成判断该创建哪个类的工作就好了。最后,一定要记得,工厂类静态方法返回一个对象。不是两个,更不是三个。

基本的工厂类:

//要创建对象实例的类
class MyObject{
}
 //工厂类
class MyFactory{
public static function factory(){
return new MyObject():
 }
}
$instance=MyFactory::factory();

一个稍微复杂的工厂模式:

<?php
interface Transport{
 public function go();
}
class Bus implements Transport{
 public function go(){
  echo "bus每一站都要停";
 }
}
class Car implements Transport{
 public function go(){
  echo "car跑的飞快";
 }
}
class Bike implements Transport{
 public function go(){
  echo "bike比较慢";
 }
}
class transFactory{
 public static function factory($transport)
 {
  switch ($transport) {
   case 'bus':
    return new Bus();
    break;
   case 'car':
    return new Car();
    break;
   case 'bike':
    return new Bike();
    break;
  }
 }
}
$transport=transFactory::factory('car');
$transport->go();

需要工厂静态方法为factory()的时候,千万别再傻乎乎的把工厂类命名为Factory了。为啥啊?别忘了同名构造函数的事儿啊~

最后还是谈点感受吧,很多新手比较眼高手低,刚刚会了if..else..,session,cookie就要来点高大上的了。与人交谈动辄可扩展性,可维护性之类云云,至于实例的话,就会一时语塞。有时候觉得,无论自己写代码还是和别人学习,都处于“众里寻他千百度”的时候,真正踏实学习后,蓦然回首,“那人却在灯火阑珊处”,大呼:“原来这TM就是***啊”。

笔者不敢承认自己会模式设计,我也是个不足一年的初学者,分享博客只是想记录自己的学习历程,能得到知道更是求之不得。如果能给别人带来帮助,那就更好啦~~~

php单列模式

模式设计是什么?

     初学者一开始会被这高大上的名称给唬住。而对于有丰富编程经验的老鸟来说,模式设计又是无处不在。很多接触的框架就是基于各种模式设计形成的。 简单说,在写代码的过程中一开始往往接触的是面向过程的,简单的基础的编程。这个时候我们往往追求的是代码能够实现某项功能就万事大吉。管他代码多么冗余,管他代码是否可重用,管他效率如何,能实现功能就好。但是,真正应用于实际的,更被大家采纳的是那些高效的,可重用的,便于团队开发的代码。基于这些因素,你不能像练手一样,随便命名函数名,随便放置脚本。模式设计告诉是给人们组织代码提供一种思路,实现可重用代码、让代码更容易被他人理解、保证代码可靠性。

在所有模式设计中,有三种基础设计模式,单例模式,工厂模式,注册树模式,其他模式往往基于这几种模式,下面介绍的是单例模式。

什么是单例模式?

根据这个名称,我们很容易了解到,单例模式指的是在整个应用中只有一个对象实例的设计模式。

为什么要用单例模式?

php常常和数据库打交道,如果在应用中如果频繁建立连接对象,进行new操作的话,会消耗大料的系统内存资源,这并不是我们希望看到的。再则,在团队合作项目中,单例模式可以有效避免不同程序员new自己的对象,造成人为的系统消耗。

如何建立单例模式?

在看到这个问题的时候,相信优秀的程序员很可能自己试着根据要求去创建单例模式,而不是坐等前人的经验。区别于其他博友告诉你什么样的模式是单例模式,我人更愿意和有面向对象编程基本经验的你考虑一下如何自己建立单例模式。

我们首先从题目出发,单例模式是只有一个对象实例的设计模式。这一点是很让人蛋疼的。我们平常创建的类不是能创建很多对象的,就是不能创建对象的(抽象类)。要创建对象需要有类这是必须的,而且不能是抽象类。这个类要防止别人可以多次创建函数。我们自然而然考虑到了从构造函数入手。但是,每次new操作都会调用构造函数,也就是会多次创建对象实例。这和我们设计初衷相悖了。在此处务必申明构造函数为private或者protected这样才能解决这个问题。

构造函数被申明为private或者protected这注定无法通过new的方法创建实例对象了。而且我们发现,经过这一步处理后,解决问题的前景变得明朗起来?为什么呢?既然无法通过new方法创建对象实例,那么我们只能通过类内的方法来创建对象实例了。 这个时候我们面临一个有趣的先有鸡还是先有蛋的问题。我们往往往往是创建了对象后才调用对象的方法,而此时需要调用类里面的方法来创建对象。不受是否创建对象影响都能调用的方法的解决方案毋庸置疑那就是利用关键字--static。

在类内创建静态方法完成完成什么工作呢?回归主题:确保只创建一个实例对象。如何确保只有一个呢?这很简单,if判断一下啊。存在的话直接返回,不存在自己创建一个嘛。当然这个实例对象是类的静态属性。至此,单例模式要求的功能实现完成。真的完成了么?还不算~如果有个类继承本类,将构造方法申明为public那不又坏事儿了?那有必要在构造方法前加final关键字了。

最后贴上单例模式代码,代码解释都在上面了~~

<?php
class Single{
 public $hash;
 static protected $ins=null;
  final protected function __construct(){
  $this->hash=rand(1,9999);
 }
 static public function getInstance(){
  if (self::$ins instanceof self) {
   return self::$ins;
  }
  self::$ins=new self();
  return self::$ins;
 } 
}

本身单例模式并不复杂,但需要深入理解。很多初学者依旧会感叹:卧槽,构造方法原来不一直是public啊~卧槽还可以不通过new创建对象啊~其实笔者想说,不管构造方法被申明为public,private还是protected,最终创建对象的时候都会调用。一直是new创建对象实例,单例模式也用new创建对象,只是换个地方而已,从类外到类内。

最后对研究出各种精妙的模式设计的程序员表示拜服~~

PHP 相关文章推荐
Windows下的PHP5.0安装配制详解
Sep 05 PHP
php开发工具之vs2005图解
Jan 12 PHP
理解php原理的opcodes(操作码)
Oct 26 PHP
Linux下实现PHP多进程的方法分享
Aug 16 PHP
PHP 安全检测代码片段(分享)
Jul 05 PHP
PHP脚本监控Nginx 502错误并自动重启php-fpm
May 13 PHP
php动态绑定变量的用法
Jun 16 PHP
UPUPW 更新 64 位 Apache 系列 PHP 7.0 正式版
Dec 08 PHP
visual studio code 调试php方法(图文详解)
Sep 15 PHP
laravel框架中路由设置,路由参数和路由命名实例分析
Nov 23 PHP
PHP实现笛卡尔积算法的实例讲解
Dec 22 PHP
PHP7 参数处理机制修改
Mar 09 PHP
PHP中error_reporting()用法详解
Aug 31 #PHP
大家在抢红包,程序员在研究红包算法
Aug 31 #PHP
微信公众平台开发之天气预报功能
Aug 31 #PHP
百度地图经纬度转换到腾讯地图/Google 对应的经纬度
Aug 28 #PHP
PHP7.0安装笔记整理
Aug 28 #PHP
php中二维数组排序问题方法详解
Aug 28 #PHP
php页面,mysql数据库转utf-8乱码,utf-8编码问题总结
Aug 27 #PHP
You might like
PHP-MySQL教程归纳总结
2008/06/07 PHP
神盾加密解密教程(二)PHP 神盾解密
2014/06/08 PHP
utf-8编码引起js输出中文乱码的解决办法
2010/06/23 Javascript
利用Keydown事件阻止用户输入实现代码
2014/03/11 Javascript
教你如何使用PHP输出中文JSON字符串
2014/05/22 Javascript
Javascript基础教程之定义和调用函数
2015/01/18 Javascript
深入理解JavaScript系列(19):求值策略(Evaluation strategy)详解
2015/03/05 Javascript
jquery 全选、全不选、反选效果的实现代码【推荐】
2016/05/05 Javascript
利用vue + element实现表格分页和前端搜索的方法
2017/12/25 Javascript
angularjs $http调用接口的方式详解
2018/08/13 Javascript
vue项目打包后上传至GitHub并实现github-pages的预览
2019/05/06 Javascript
微信公众号获取用户地理位置并列出附近的门店的示例代码
2019/07/25 Javascript
使用axios请求接口,几种content-type的区别详解
2019/10/29 Javascript
iSlider手机端图片滑动切换插件使用详解
2019/12/24 Javascript
JavaScript如何判断对象有某属性
2020/07/03 Javascript
js实现鼠标拖曳效果
2020/12/30 Javascript
python网络编程学习笔记(四):域名系统
2014/06/09 Python
Python实现读取目录所有文件的文件名并保存到txt文件代码
2014/11/22 Python
Python实现的Google IP 可用性检测脚本
2015/04/23 Python
Python守护进程和脚本单例运行详解
2017/01/06 Python
浅析python递归函数和河内塔问题
2017/04/18 Python
利用matplotlib+numpy绘制多种绘图的方法实例
2017/05/03 Python
Python cookbook(数据结构与算法)找出序列中出现次数最多的元素算法示例
2018/03/15 Python
Python中应该使用%还是format来格式化字符串
2018/09/25 Python
Python从文件中读取指定的行以及在文件指定位置写入
2019/09/06 Python
完美解决pycharm导入自己写的py文件爆红问题
2020/02/12 Python
python网络编程socket实现服务端、客户端操作详解
2020/03/24 Python
python hmac模块验证客户端的合法性
2020/11/07 Python
CSS3点击按钮实现背景渐变动画效果
2016/10/19 HTML / CSS
建筑项目策划书
2014/01/13 职场文书
文明餐桌活动方案
2014/02/11 职场文书
yy司仪主持词
2014/03/22 职场文书
优秀大学生求职自荐信范文
2014/04/19 职场文书
农业项目建议书
2014/08/25 职场文书
道士塔读书笔记
2015/06/30 职场文书
运动会致辞稿
2015/07/29 职场文书