设计模式 一 值对象模式(The Value Object Pattern)

TestRent();

function TestRent() {
    $game = new Monopoly;
    $player1 = new Player('Madeline', 1000);
    $player2 = new Player('Caleb', 1500);
    
    $game->payRent($player1, $player2, new Dollar(20));
    echo $player1->getBalance();
    echo $player2->getBalance();
}

class Monopoly {
    /**
    * pay rent from one player to another
    * @param Player $from the player paying rent
    * @param Player $to the player collecting rent
    * @param Dollar $rent the amount of the rent
    * @return void
    */
    public function payRent($from, $to, $rent) {
        $to->collect($from->pay($rent));
    }
}


class Player {
    protected $name;
    protected $savings;

    public function __construct($name, $dollar = 1500) {
        $this->name = $name;
        $this->savings = new Dollar($dollar);
    }

    public function collect($amount) {
        $this->savings = $this->savings->add($amount);
    }
    
    public function pay($amount) {
        $this->savings = $this->savings->debit($amount);
        return $amount;
    }

    public function getBalance() {
        return $this->savings->getAmount();
    }
}

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());
    }
}

值对象模式

大意理解是,如果代码写的不正确,程序会改变一些不希望改变的值,并造成错误,在例子中,有说明一个存在bug的程序....并做出解释....其实我在思考那个程序......后面写了一个Person的类,用这个类调用BadDollar 类和Work类的一些东西,person被实例化了两次...其实...person这个类里面并没有任何的方法,所以无论对它实例化n次,都对前面两个类不起作用,所以当然得到的值,会看上去相互影响了...其实我觉得这个和person这个类 是没有任何关系的...

实例化person后,希望只修改p1的工资,结果却对p2起了作用,原因是在第一次实例化p1的时间,就改变了值,自然p2的值也被修改了,得到了不想要的结果.那么,不喜欢那个值发生变化,是否可以使用私有的属性呢,保证这个变量不会被外界所影响,但是又可以通过其他方式访问....我要再想一想.....

我的解决办法是,分别对work这个类做实例化,$job = new work; $job1 = new work; 然后用person去访问不同的实例化后的work 这样就不会产生相互影响了

我看看作者是用的什么办法...

作者的方法当然比我高明的多,代码如下(作者有用他自己的一个架构,我这里没有)

<?
class Dollar{
protected $amount;
function __construct($amount=0){
   $this->amount = $amount;
}
function getAmount(){
   return $this->amount;
}
function add($dollar){
return new Dollar($this->amount+$dollar);
}
}

$a = new Dollar;
$a->add(200);
$a->add(400);
print_r($a->add(200));
print_r($a->add(400));
?>

得出的结果,是并没有相互影响,只是有点不明白为什么返回的书数组

作者对代码解释如下

在这种情况下,虽然没有设定函数Dollar::amount(),但在对象的实例化期时,参数Dollar::amount就已经被赋值了。而函数Dollar::getAmount()只是提供一个访问Dollar属性的功能,在这里访问的数据类型为浮点型。

最有趣的变化是在Dollar::add()方法函数中。并不是直接改变$this->amount变量的值从而会改变已存在的Dollar对象实例,而是创建并返回一个新的Dollar实例。现在,尽管你指定当前对象给多个变量,但是每一个变量的变化都不会影响其它的变量实例。

对于价值设计模式不变性是关键,任何对于一个Value Object的变量amount的改变,是通过创建一个新的带有不同预期值的类的实例来完成的。上文中提高的最初那个$this->amount变量的值从未改变。

简单来说,在PHP5里面使用价值设计模式时,需要注意以下几个方面:

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

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

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

以上三步创建了一个不变的值,这个值一旦被初始化设置之后就不能被改变。当然,你也应该提供一个查看函数或者是访问Value Object的属性的方法,并且可以添加一些与这个类相关的函数。值对象并不是只能用在一个简单的架构上,它也可以实现重要的商务逻辑应用。

我再认真读一下,再写心得

认真看了下,作者说:通过创建一个新的带有不同预期值的类的实例来完成的,嗯....高明的地方就是在创建的时候,就把自己实例化了,所以$a->add(200);$a->add(400);一样得到的是两个实例化后的结果,并无相互影响。

保证值对象模式的关键作者也说了

设置private 或者protected保证初始值不被外界访问方式修改(protected 继承的时候能修改)

利用构造函数对属性的修改赋值 其意义也是如此 不希望被外界修改

去掉改变值属性的函数 其实三点说的都是一个东西,保证值不被修改

总重要的地方 是不是应该是对对象的不同实例化,就如作者这样呢?

今天在周兄的提示下,进一步思考值对象模式,以下是进一步的理解

所谓值对象模式,从字面意思就好理解,以前我们使用的都是传递的值,把得到的值进行传递,现在我们用的方式是把对象作为值来传递,传递的是对象,不是值,这样我们就把值隐藏起来了,保证不被外界访问或者破坏,你要得到这个值也行啊,用我提供的方式去得到吧,但是外界不可以修改.....

我想这个就是值对象模式的好处吧

php的若干设计模式,其实就是面向对象方式的一些优秀的写法,如果只是凭借想像写一些代码,可能会造成很多隐藏起来的问题,可能会有很多隐藏的bug,或者不利于团队开发,不利于二次开发,不利于修改,下一个模式,最重要的模式之一,工厂模式,我继续写




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值