zoukankan      html  css  js  c++  java
  • 【PHP设计模式】值对象模式

    值对象模式:

      下面是一个给员工发放工资的例子。但是因为PHP5的对象赋值的处理方式,所以$job::salary,、$p1::wallet和$p2::wallet这三个看上去不同的对象实例虽然使用着不同的“标识符”,但事实上,它们全部都指定到同一个实例对象。

    //值对象模式
    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();//200
    $p1->wallet->add($job->payDay());//400
    $doller1 = $p1->wallet->getAmount();
    
    $p2->wallet = $job->payDay();
    print_r($p2->wallet->getAmount());//400
    $p2->wallet->add($job->payDay());
    $doller2 = $p2->wallet->getAmount();//800
    
    $p3->wallet = $job->payDay();//800
    $p3->wallet->add($job->payDay());
    $doller3 = $p3->wallet->getAmount();//1600
    echo $doller1."|".$doller2."|".$doller3;

      发放工资的操作(PayDay表示发放工资的日子,这里表示发放工资的动作),使用$job->payDay()本来仅仅是想增加$P1的工资,却出乎意料地次给$P2也发放了工资,导致了$p2初始工资变成了400。

     

    做如下改动修复BUG:

    值对象模式
    //值对象模式
    class BadDollar {
        protected $amount;
        public function __construct($amount=0) {
            $this->amount = (float)$amount;
        }
        public function getAmount() {
            return $this->amount;
        }
        public function add($dollar) {
            return new BadDollar($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();//200
    $wallet1 = $p1->wallet->add($job->payDay());
    $doller1 = $wallet1->getAmount();//400
    
    $p2->wallet = $job->payDay();
    $wallet2 = $p2->wallet->add($job->payDay());
    $doller2 = $wallet2->getAmount();//400
    
    $p3->wallet = $job->payDay();
    $wallet3 = $p3->wallet->add($job->payDay());
    $doller3 = $wallet3->getAmount();//400
    echo $doller1."|".$doller2."|".$doller3;//400|400|400

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

    对于值对象设计模式不变性是关键,任何对于一个Value Object的变量amount的改变,是通过创建一个新的带有不同预期值的类的实例来完成的

    1. 保护值对象的属性,禁止被直接访问。
    2. 在构造函数中就对属性进行赋值。
    3. 去掉任何一个会改变属性值的方式函数(setter),否则属性值很容易被改变。
  • 相关阅读:
    算法导论(第三版)Exercises2.1(插入排序、线性查找、N位大数相加)
    含铝馒头可能损伤儿童的智力
    每秒3600乘以100等于36万次售票解决方案
    namespace Measure
    public interface ICloneable
    VB.net 与线程
    C#调用VP 包含素材
    C# 定时器 一个简单 并且可以直接运行的Demo
    松下 激光位移传感器 API
    在Win7系统下, 使用VS2015 打开带有日文注释程序出现乱码的解决方案
  • 原文地址:https://www.cnblogs.com/colorstory/p/2716297.html
Copyright © 2011-2022 走看看