• --:)欢迎访问锋网源码(:--
  • 首页
  • RSS订阅
  • 常用软件
  • 网页模板
  • 网站运作
  • 锋网学院
  • 繁體中文

  • 学院首页
  • 新闻资讯
  • 网站运营
  • 网站开发
  • 美工设计
  • 数据库类
  • 服务器类
  • 网络应用
  • 操作系统
  • 软件教学
编程开发   认证考试   网络安全   文章搜索: 高级搜索
会员登录/控制面版 您的位置: 学院首页 >> 网站开发 >> PHP教程 >> 文章内容
 

精彩推荐

 
 

本类推荐文章

  • PHP的十个高级技巧
  • PHP找回密码机制流程
  • 解决phpmyadmin 乱码,支持gb..
 
 

本类阅读排行

  • PHP的十个高级技巧
  • PHP找回密码机制流程
  • Windows XP下PHP+MySQL环境搭..
  • PHP链接ACCESS数据库简单的方..
  • 解决phpmyadmin 乱码,支持gb..
  • PHP代码加密解密一法
  • 如何基于discuz开发网站通行..
  • PHP中格式化显示时间
  • 一个简单计数器的源代码
  • 简体中文转换为繁体中文的PH..
  • php命令行脚本多进程并发执行..
  • PHP/MySQL教程 完整教程
  • 一生成柱状图、横柱图、折线..
  • PHP 字符串操作入门教程
  • PHP入门速成
  • 做个自己站内搜索引擎
  • PHP代码:得到客户端的IP
  • 用PHP制作动态计数器
  • 实现统计在线人数/用户列表
  • AJAX在PHP中的简单使用
 
 

php教程:php设计模式介绍之值对象模式

  • 日期:2008-04-11     人气:     出处:phpchina     作者: forest
  • 字体大小:
  • 小
  • 中
  • 大

PHP4样本代码:

和PHP5不一样的是,PHP4赋值对象资源的时候是拷贝该对象,这个语法的特点本质上和值对象设计模式要求正好吻合。

然而,PHP4不能控制的属性和方法函数在对象之外的可见性,所以实现一个值对象设计模式相对PHP5也有细微的差别。

网页教学网

假如你回想一下这本书序言中的“对象句柄”部分,它提出了三个 “规则”,当你在PHP4中使用对象去模仿PHP5中的对象句柄时,这三个规则总是适用的:

  1. 通过指针($obj=&new class;)来创建对象。
  2. 用指针(function funct(&$obj) param{})来传递对象。
  3. 用指针(function &some_funct() {} $returned_obj =& some_funct())来获取一个对象。

然后,值对象设计模式却不能使用上述三个“总是适用”的规则。只有忽视了这些规则,才能总是得到一个PHP4对象的拷贝(这相当于PHP5中的“克隆”操作,描述在http://www.php.net/manual/en/language.oop5.cloning.php) Webjx.Com

因为PHP4可以轻松地赋值一个对象—这在PHP语言中是一个固有的行为,所以实现变量的不可更改就需要通过值对象通用协定来实现。在PHP4中,如果要使用值对象,请不要通过指针来创建或获取一个对象,并且给所有需要保护以免外界修改的属性或者方法函数命名时,都在属性和方法函数的名字加上下划线(_)做前缀。按照协定,变量如果具有值对象的属性,应该使用一个下划线来标识它的私有性。

Webjx.Com

下面是PHP4中的Dollar类:

下面这个实例可以说明,你不能在PHP4中限制一个属性只能被外部更改: Webjx.Com

function TestChangeAmount() {
$d = new Dollar(5);
$this->assertEqual(5, $d->getAmount());
//only possible in php4 by not respecting the _private convention
$d->_amount = 10;
$this->assertEqual(10, $d->getAmount());
}

再重复一次,在所有PHP4对象中,私有变量的前缀使用一个下划线,但是你还是可以从外部来直接访问私有属性和方法函数。

值对象中的商业逻辑

网页教学网

值对象(Value Objects)不仅仅用于最小限度的访问方法这样的简单的数据结构,它同样还可以包括有价值的商业逻辑。考虑以下你如果实现许多人中平均分配金钱。

Webjx.Com

如果总钱数确实是可以分成整数,你可以生成一组Dollar对象,而且每一个Dollar对象都拥有相同的部分。但是当总数可以整数的美元或者美分的时候,我们该怎么处理呢?

让我们开始用一个简单的代码来测试一下:

// PHP5
function testDollarDivideReturnsArrayOfDivisorSize() {
$full_amount = new Dollar(8);
$parts = 4;
$this->assertIsA(
$result = $full_amount->divide($parts)
,’array’);
$this->assertEqual($parts, count($result));
}
Webjx.Com

注释 assertIsA:

assertIsA()的作用是让你测试:一个特定的变量是否属于一个实例化的类。当然你也可以用它来验证变量是否属于一些php类型:字符串、数字、数组等。

为了实现上述测试, Dollar::divide()方法函数的编码如下…

public function divide($divisor) {
return array_fill(0,$divisor,null);
}

最好加上更多的细节。

网页教学网

function testDollarDrivesEquallyForExactMultiple() {
$test_amount = 1.25;
$parts = 4;
$dollar = new Dollar($test_amount*$parts);
foreach($dollar->divide($parts) as $part) {
$this->assertIsA($part, ‘Dollar’);
$this->assertEqual($test_amount, $part->getAmount());
}
}

现在,应当返回存有正确数据的Dollar对象,而不是简单的返回数量正确的数组。

实现这个仍然只需要一行语句:

Webjx.Com

最后一段代码需要解决一个除数不能把Dollar的总数均匀的除开的问题。 Webjx.Com

这是一个棘手的问题:如果存在不能均匀除开的情况,是第一部分还是最后一部分能得到一个额外的金额(便士)?怎样独立测试这部分的代码?

一个方法是:明确指定代码最后需要实现目标:这个数组的元素数量应该是与除数表示的数量相等的,数组的元素之间的差异不能大于0.01,并且所有部分的总数应该与被除之前的总数的值是相等的。

上面的描述通过正如下面的代码实现:

function testDollarDivideImmuneToRoundingErrors() {
$test_amount = 7;
$parts = 3;
$this->assertNotEqual( round($test_amount/$parts,2),
$test_amount/$parts,
’Make sure we are testing a non-trivial case %s’);
$total = new Dollar($test_amount);
$last_amount = false;
$sum = new Dollar(0);
foreach($total->divide($parts) as $part) {
if ($last_amount) {
$difference = abs($last_amount-$part->getAmount());
$this->assertTrue($difference <= 0.01);
}
$last_amount = $part->getAmount();
$sum = $sum->add($part);
}
$this->assertEqual($sum->getAmount(), $test_amount);
}

注释 assertNotEqual:

网页教学网

当你要确保两个变量的值是不相同时,你可以用它来进行检验。这里面的值相同是PHP的”==”运算符进行判断的。任何情况下当你需要确保两个变量的值是不相同的时候,你就可以使用它。

网页教学网

现在根据上述代码,如果来构造Dollar::divide()方法函数呢? 网页教学网

class Dollar {
protected $amount;
public function __construct($amount=0) {
$this->amount = (float)$amount;
}
public function getAmount() {
return $this->amount;
}
public function add($dollar) {
return new Dollar($this->amount + $dollar->getAmount());
}
public function debit($dollar) {
return new Dollar($this->amount - $dollar->getAmount());
}
public function divide($divisor) {
$ret = array();
$alloc = round($this->amount / $divisor,2);
$cumm_alloc = 0.0;
foreach(range(1,$divisor-1) as $i) {
$ret[] = new Dollar($alloc);
$cumm_alloc += $alloc;
}
$ret[] = new Dollar(round($this->amount - $cumm_alloc,2));
return $ret;
}
}

网页教学网

这段代码可以正常运行,但是仍然有一些问题,考虑一下如果在testDollarDivide()的开始处改变$test_amount 为 0.02; $num_parts 为 5;这样的临界条件,或者考虑一下当你的除数不是一个整型数字,你该怎么做?

Webjx.Com

解决上边这些问题的方法是什么呢?还是使用测试导向的开发循环模式:增加一个需求实例,观察可能的错误,编写代码来生成一个新的实例进行运行,还有问题存在时继续分解。最后重复上述过程。

 

public function divide($divisor) {

return array_fill(0,$divisor,new Dollar($this->amount / $divisor));

网页教学网

 

网页教学网

// PHP4
class Dollar {
var $_amount;
function Dollar($amount=0) {
$this->_amount = (float)$amount;
}
function getAmount() {
return $this->_amount;
}
function add($dollar) {
return new Dollar($this->_amount + $dollar->getAmount());
}
function debit($dollar) {
return new Dollar($this->_amount - $dollar->getAmount());
}
}

网页教学网

[1] [2] [3] [4]
相关文章
  • php教程:经典PHP代码
  • php教程:mysql的常用语句
  • PHP教程:cookie和数组的结合实现购物车
  • php教程:mysql数据库操作的DB类
  • php教程:php设计模式之编程惯用法
  • php教程:php设计模式之前言
  • PHP新手上路(一)
  • 来自PHP.NET的入门教程
  • PHP新手上路(二)
  • PHP新手上路(四)
相关软件

  • 网友评论:
  • 查看所有评论
  • 我要发表评论
 

关于本站 | 广告联系 | 版权声明 | 网站地图 | 加入收藏 | 帮助中心 |

Copyright © 2006-2007 fwvv.net  程序支持:木翼  皖ICP备06004916号