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()来获取一个对象。
没有评论:
发表评论