2010年2月22日星期一

PHP值对象模式

[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;
}

require_once 'simpletest/unit_tester.php';

require_once 'simpletest/reporter.php';

// the test

class TestingTestCase extends UnitTestCase {

function testBadDollarWorking() {
$job = new Work;
$p1 = new Person;
$p2 = new Person;
$p1->wallet = $job->payDay();
$this->assertEqual(200, $p1->wallet->getAmount());
$p2->wallet = $job->payDay();
$this->assertEqual(200, $p2->wallet->getAmount());
$p1->wallet->add($job->payDay());
$this->assertEqual(400, $p1->wallet->getAmount());
//this is bad — actually 400
$this->assertEqual(200, $p2->wallet->getAmount());
//this is really bad — actually 400
$this->assertEqual(200, $job->payDay()->getAmount());

}
}
$test = new TestingTestCase('Testing Unit Test');

$test->run(new HtmlReporter());
[/php]

这是书上的例题。说实在话,开始我并没有搞清楚问题出在那~。
书上解说p1和p2用的是同一个BadDollar的对象实例。按照以往的思维,对于这句话是难于理解的,p1和p2都是新创建的对象,而不是如p2=p1这样赋值,它们怎么会使用同样的对象呢?当然,如果记得PHP5对象赋值的原理,肯定就不难理解了。因为PHP5的对象赋值的处理方式,所以$job::salary,$p1::wallet和$p2::wallet这三个看上去不同的对象实例虽然使用着不同的“标识符”,但实际上,它们全都指定到了同一个对象实例。

另外,执行Value Object时,php4和php5是有区别的。PHP4操作所有的对象都遵循Value Objects对象规律的——它的赋值操作相当于对对象做了一个拷贝。

[php]
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());
}
}
[/php]
PHP5里用值对象设计模式时,需要注意以下几个方面:

  • 保护值对象的属性,禁止被直接访问。

  • 在构造函数中就对属性进行赋值。

  • 去掉任何一个会改变属性值的方式函数,否则属性值很容易被改变。



PHP4中使用对象去模仿PHP5中的对象句柄时的三个规则:

  • 通过指针 $obj =& new class; 来创建对象。

  • 用指针 function funct(&$obj) param{} 来传递对象。

  • 用指针 function &some_funct() {} $returned_obj =& some_funct() 来获取一个对象。

没有评论 :

发表评论