PHP设计模式实例学习笔记
一、值对象模式
再说设计模式-值对象模式之前,你要了解值传递和引用传递:
1.值对象模式概念:
如果你把同一个对象资源赋值给两个不同的变量,然后改变其中的一个变量,另一个变量仍然不受影响。这就是使用值对象模式的目的。
看下面例子:
代码如下 | 复制代码 |
<?php class BadDollar { protected $amount; public function __construct($amount=0) { $this->amount = (float)$amount; } public function getAmount() { return $this->amount; } public function add($dollar) { $this->amount += $dollar->getAmount(); } } class Work { protected $salary; public function __construct() { $this->salary = new BadDollar(200); } public function payDay() { return $this->salary; } } class Person { public $wallet; } $job = new Work; $p1 = new Person; $p2 = new Person; $p1->wallet = $job->payDay(); print_r($p1->wallet->getAmount()); //200 $p2->wallet = $job->payDay(); print_r($p2->wallet->getAmount()); //200 $p1->wallet->add($job->payDay()); print_r($p1->wallet->getAmount()); //400 //this is bad — actually 400 print_r($p2->wallet->getAmount()); //400 //this is really bad — actually 400 print_r($job->payDay()->getAmount()); //400 |
看上面例子,可以知道明显的错误是$p1和$p2使用的是同一个BadDollar对象,首先,类Work和类Person的实例已经创建。那么,假设每一个雇员最初有一个空的电子钱包,雇员的电子钱包Person:wallet是通过Work::payDay()函数返回的对象资源变量赋值的,所以被设定为一个BadDollar类的对象实例。实际上,$job::salary,、$p1::wallet和$p2::wallet指向的是同一个对象的实例。
使用值对象模式,重新设计Dollar对象如下
代码如下 | 复制代码 |
class Dollar { |
可以看到,主要的变化在于Dollar:add()函数中,它是创建并返回一个新的Dollar实例,所以,尽管你指定当前对象给多个变量,但是每一个变量的变化都不会影响其它的变量实例。
值对象模式设计注意:
1.保护值对象的属性,禁止被直接访问。
2.在构造函数中就对属性进行赋值。
3.去掉任何一个会改变属性值的方式函数(setter),否则属性值很容易被改变
二、策略模式
1.策略模式概念
策略模式针对一组算法,将每一个算法封装到具有共同接口的独立的类中,此模式让算法的变化独立于使用算法的客户。从而让程序结构更灵活,具有更好的扩展性和维护性
2.策略模式结构图
3.策略模式角色说明
抽象策略(Strategy)角色:定义所有支持的算法的公共接口。通常是以一个接口或抽象来实现。Context使用这个接口来调用其ConcreteStrategy定义的算法。
具体策略(ConcreteStrategy)角色:以Strategy接口实现某具体算法
环境(Context)角色:持有一个Strategy类的引用,用一个ConcreteStrategy对象来配置
4.策略模式实例
比如说购物车系统,在给商品计算总价的时候,普通会员肯定是商品单价乘以数量,但是对中级会员提供8者折扣,对高级会员提供7折折扣,这种场景就可以使用策略模式实现:
代码如下 | 复制代码 |
<?php //抽象策略角色《为接口或者抽象类,给具体策略类继承》 |
三、命令模式
1.命令模式概念:
将来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参数化。用于“行为请求者”与“行为实现者”解耦,可实现二者之间的松耦合,以便适应变化。
2.参与者:
- Command(命令):在一个方法调用之上定义一个抽象;
- ConcreteCommand(具体的命令):一个操作的实现;
- Invoker(调用者):引用Command实例作为它可用的操作。
代码如下 | 复制代码 |
<?php //命令 interface Validator { /** * The method could have any parameters. * @param mixed * @return boolean */ public function isValid($value); } //具体命令 class MoreThanZeroValidator implements Validator { public function isValid($value) { return $value > 0; } } //具体命令 class EvenValidator implements Validator { public function isValid($value) { return $value % 2 == 0; } } //调用者 class ArrayProcessor { protected $_rule; public function __construct (Validator $rule) { $this->_rule = $rule; } public function process(array $numbers) { foreach ($numbers as $n) { if ($this->_rule->IsValid($n)) { echo $n, " "; } } } } //客户端 $processor = new ArrayProcessor(new EvenValidator()); $processor->process(array(1, 20, 18, 5, 0, 31, 42)); |
在这个模式中,Invoker(调用者)知道传递给它的Command,无需依赖于真实的ConcreteCommand(具体的命令)实现,解决了通过配置进行方法调用相关的问题,如UI控件按钮和菜单等引用一个Command,它们的行为是通过通用的ConcreteCommand实例呈现的。
四、观察者模式
首先了解观察者模式的概念:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。看下面例子你就明白了!
1.使用观察者模式实现消息推送
代码如下 | 复制代码 |
<?php //观察者
|
如果你使用的确php代码我们可以使用$_SERVER[HTTP_X_REWRITE_URL]与ORIG_PATH_INFO来判断你所使用的环境是iis还是apache了
例
if(isset($_SERVER['HTTP_X_REWRITE_URL'])) // IIS
else if(isset($_SERVER['ORIG_PATH_INFO'])) // IIS 5.0 CGI
//以上两行代码,在yii里的,原样复过来的。
//只作参考
在php中条件语句主要用到if else与if elseif及swicth case之类的语句了,这两语句是用到最多的,下面我来给大家普通一下。
一、if…else语句
if...else 语句
在条件成立时执行一块代码,条件不成立时执行另一块代码
语法:
1、简单条件
if(条件){
……
}
else{
……
}
例
代码如下 | 复制代码 |
<?php |
范例:本例的执行部分有三行,不可省略大括号。
代码如下 | 复制代码 |
<?php |
2、复杂条件
elseif 语句
与 if...else 配合使用,在若干条件之一成立时执行一个代码块
if(条件){
……
}
elseif(条件){
……
}
else{
……
}
例
范例:上面的例子来修改成更完整的处理。其中的 else 由于只有一行执行的指令,因此不用加上大括号。
代码如下 | 复制代码 |
<?php $f="/usr/local/lib/php3.ini"; if (file_exists($f)) { echo "以下是 PHP3 的配置文件<p><pre>n"; readfile($f); echo "</pre>n"; } else echo "很抱歉,找不到 $f"; ?> |
--------------------------------------------------------------------------------
第三种就是递归的 if..else 循环,通常用在多种决策判断时。它将数个 if..else 拿来合并运用处理。
直接看下面的例子
代码如下 | 复制代码 |
<?php |
上例只用二层的 if..else 循环,用来比较 a 和 b 两个变量。实际要使用这种递归 if..else 循环时,请小心使用,因为太多层的循环容易使设计的逻辑出问题,或者少打了大括号等,都会造成程序出现莫名其妙的问题
二、Switch语句
1 语法:
switch(表达式){
case 值1:
语句
break;
case 值2:
语句
break;
default:
没有匹配的值时执行的语句
}
工作原理:
1.对表达式(通常是变量)进行一次计算
2.把表达式的值与结构中 case 的值进行比较
3.如果存在匹配,则执行与 case 关联的代码
4.代码执行后,break 语句阻止代码跳入下一个 case 中继续执行
5.如果没有 case 为真,则使用 default 语句
例
代码如下 | 复制代码 |
<?php |
另外一个实例,利用switch实现一个页面多用途,首先建立test.php页面:
代码如下 | 复制代码 |
<?php |
接着,让我们看看solution.php是如何处理这四种操作的。
代码如下 | 复制代码 |
<?php switch ($action) |
很简单,我们首先接收到action的值,运用switch语句根据action值的不同分别赋予它相应的操作。怎么样,是不是比大家想象中要简单很多?
大括号是php中一个非常常用到的符号了,他不是变量也不是常量那它到底是什么呢,下面我一起来看看大括号在php中使用实例吧。
刚用到一个由字符串来设定对像属性名的功能。发现大括号的作用真强….
1. 动态设置对象的属性名的使用:
写法一(不能正确设置):
$obj->$string[$key]; //这里只能使用$string的0位置的字符作为属性名值,如:$string = 'string'; $obj->$string[$key] 等同于$obj->s[$key];
写法二(可以正确设置):
$obj->{$string}[$key]; //这里的大括号有点类似于运算中的小括号的作用,即先算大括号里面的内容。但是请注意:
写法三(错误的写法):
$obj->($string)[$key]; // 直接报错!
2. 检测字符串的长度中使用:
$string = 'string';
if(isset($string{8})) {
echo 'Is set!';
} else {
echo 'Not set!';
}
3. 像字符串中使用变量的时候也要用到,如:
echo "{$string}, {$obj->string}";
在php中empty(), is_null(), isset()三个函数都可以用来判断变量是否存在的,那么empty(), is_null(), isset()之间的区别在哪里呢,如果你不明白我一起来看看下文。
empty(), is_null(), isset()真值表(区别)
我们先来看看这3个函数的功能描述 www.111cn.net
isset 判断变量是否已存在,如果变量存在则返回 TRUE,否则返回 FALSE。
empty 判断变量是否为空,如果变量是非空 或非零 的值,则 empty() 返回 FALSE。换句话说,"" 、0 、"0" 、NULL 、FALSE 、array() 、var $var; 以及没有任何属性的对象 都将被认为是空的,如果变量为空,则返回 TRUE。
is_null 判断变量是否为NULL
怎么样,一般的都是这种解释,但这种解释已经很让人迷糊了,下面结合具体的例子来分析吧!
从中我们可以发现只要变量是""或者0,或者是false和null,只要是这些值empty都会返回true。
isset只是判断变量是否存在,只要你这个变量不是null或未赋值,返回结果都是true。若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。同时要注意的是一个 NULL 字节("")并不等同于 PHP 的 NULL 常数。
而is_null正好是isset的反结果,我们可以把它看成是!isset,是isset的一个逆操作。
从以上的例子中,我们也可以得出下面这几个结论(以后编程中会经常用到的哦):
假设 $var 是任何type
当 empty($var) 为 true 时,(bool)($var) 为 false 。反之亦然。
当 is_null($var) 为 true 时,isset($var) 为 false 。反之亦然。
例如:
$i=$j+1;
这里的is_null($j)为true(可以理解为因为 isset($j)为false,因为没有事先声明 $j 这个变量)
另外需要注意的两点是:
(1)empty() 只检测变量,检测任何非变量的东西都将导致解析错误 。换句话说,后边的语句将不会起作用: empty(addslashes($name))。
(2)isset() 只能用于变量,因为传递任何其它参数都将造成解析错误。若想检测常量是否已设置,可使用 defined() 函数。
概括总结isset,empty,is_null区别
刚才介绍的:检查变量,以及参数类型,这个是这3个函数不同之处的基础,也是最容易被忽视的。看到网上有很多对这个3个函数进行比较文章。很少涉及这些。下面我要说的,是在都检查已存在变量情况下,不同之处。
代码如下 | 复制代码 |
<?php
|
通过上面这个简单测试,我们可以大体知道,当一个变量存在情况下:isset,empty,is_null检测,得到值情况了。上面没有举例更多变量。其实测试发现:
empty
如果 变量 是非空或非零的值,则 empty() 返回 FALSE。换句话说,""、0、"0"、NULL、FALSE、array()、var $var、未定义; 以及没有任何属性的对象都将被认为是空的,如果 var 为空,则返回 TRUE。
isset
如果 变量 存在(非NULL)则返回 TRUE,否则返回 FALSE(包括未定义)。变量值设置为:null,返回也是false;unset一个变量后,变量被取消了。注意,isset对于NULL值变量,特殊处理。
is_null
检测传入值【值,变量,表达式】是否是null,只有一个变量定义了,且它的值是null,它才返回TRUE . 其它都返回 FALSE 【未定义变量传入后会出错!】.
相关文章
- 神马是“解释器模式”?先翻开《GOF》看看Definition:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。在开篇之前还是要科普几个概念: 抽象语法树: 解释器模式并未解释如...2014-06-07
- 这篇文章主要为大家介绍了JavaScript设计模式中的装饰者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25
- 1、简介Smarty是一个使用PHP写出来的模板PHP模板引擎,是目前业界最著名的PHP模板引擎之一。它分离了逻辑代码和外在的内容,提供了一种易于管理和使用的方法,用来将原本与HTML代码混杂在一起PHP代码逻辑分离。简单的讲,目...2014-05-31
- 这篇文章主要介绍了JavaScript设计模式之职责链模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
- 这篇文章主要为大家介绍了JavaScript设计模式中的状态模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-12
- 当我们在星际中开地图和几家电脑作战的时候,电脑的几个玩家相当于结盟,一旦我们出兵进攻某一家电脑,其余的电脑会出兵救援。 那么如何让各家电脑知道自己的盟友被攻击了...2016-11-25
- 这篇文章主要为大家介绍了JavaScript设计模式中的单例模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 这篇文章主要介绍了JavaScript设计模式之命令模式,对设计模式感兴趣的同学,可以参考下...2021-04-25
- 举一个简单的date例子 我将使用echo命令把内容输出到我们的客户端(浏览器)。我将使用下面的代码做为基础代码。 代码如下 复制代码 <!DOCTY...2016-11-25
- 这篇文章主要为大家介绍了JavaScript设计模式中的责任链模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 这篇文章主要为大家介绍了JavaScript设计模式中的状态模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-14
- 这篇文章主要为大家介绍了JavaScript设计模式中的观察者模式,对JavaScript设计模式感兴趣的小伙伴们可以参考一下...2016-01-21
- 一篇Android学习笔记之多界面切换实例,希望对各位朋友有所帮助。 用过VB 、 VC#的朋友都知道,在VB或VC#里要进行窗口(界面)切换很容易 例如在VB、C#里: 有 Fom1、...2016-09-20
- 引用:意思是将原始对象在内存中的地址传递给目标对象,就相当于原始对象和目标对象指向的是同一个内存地址。此时,如果对目标对象或者原始对象进行修改,内存中的数据也会改...2016-11-25
- 这篇文章主要给大家介绍的是JavaScript中的单例模式,设计模式代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案,需要的朋友可以参考一下...2021-09-25
- 组合模式可以使客户端调用简单,它可以一致使用组合结构或是其中单个对象,简化了客户端代码。...2020-06-25
- cURL是php中一个很强大的功能,可以模仿各种用户请求,如模仿用户登录,发送php cookie等等操作,下面我来整理一些相关的方法与各位同学看看 备注:使用curl_init函数,必须...2016-11-25
- 那些年学了ASP.NET后,才开始学习C#,说来也怪,怎么学了ASP.NET才来学习C#,其实没有什么的...2020-06-25
- CWidget是所有Widget的基类。CWidget是自包含组件,可以看出是MVC的简略版,CWidget相比Controller,既没有actions,也没有filters widget,英文意思为小工具,小挂件,在程序...2016-11-25