【问题标题】:General PHP/OOP Strategy - How to communicate between nested objects通用 PHP/OOP 策略 - 如何在嵌套对象之间进行通信
【发布时间】:2012-11-15 05:05:19
【问题描述】:

使用嵌套对象时(ObjTwo 作为 objOne 的属性):

$objOne->property = new ObjTwo($objOne);

最好的沟通方式是什么?以下是我能想到的几种方法:

使用特定的 get/set 方法

class ObjTwo {
    __construct($objOne){
        $prop1 = $objOne->get_prop1(); 
        // do something with prop1
        $prop2 = $objOne->get_prop2();
        // do something with prop2

        // ... Having to write all these out is kind of a pain
        //     if you're going to have 20+ vars, and there's no
        //     easy way to loop through them.
    }
}

问题:逐行写出来,当我添加新属性时必须更新它。

我知道建议为每个属性设置一个 get/set 方法,但是我真的很想遍历数据...

get_object_vars() 怎么样

class ObjTwo {
    __construct($objOne){
        extract(get_object_vars($objOne));
        // do something with the vars
    }
}

问题:此方法绕过了使用 getter/setter 方法的能力,并且每个属性都必须是公共的才能访问。

动态 getter/setter 方法调用

我考虑过的另一种方法是创建一个字段数组,并有严格的命名 getter/setter 方法的策略:

class ObjTwo {
    __construct($objOne){
        $prop_array = array('prop1', 'prop2', 'prop_three');
        $values = array();
        foreach ($prop_array as $prop){
            $values[$prop] = $objOne->get_{$prop}();
        }
    }
}

问题: 每次添加新属性时,我都必须确保正确命名 get_method(),并更新 $prop_array。

谁有更好的解决方案?也许只是构建一个数据数组?:

$objOne->property = new ObjTwo($objOne->get_data());

我喜欢这个解决方案

考虑到这一点,这里有一点澄清:我不想只是从父母到孩子制作相同的副本,反之亦然 - 我编辑了上面的示例以更好地展示这一点。它更多的只是将对象数据的子集从一个地方传递到另一个地方的想法。

不用写了:

$first_name = $this->member->get_first_name();
$last_name = $this->member->get_last_name();
$email = $this->member->get_email();
$display_name = $this->member->get_display_name();
// etc... and
$this->member->set_first_name($first_name);
$this->member->set_last_name($last_name);
$this->member->set_email($email);
$this->member->set_display_name($display_name);
// etc..

有一个$this->member->get_fields('first_name', 'last_name', 'email', 'display_name'); 方法怎么样?我不喜欢准确地记住字段名称(fname、f_name、first_name 等),因此您可以使用类常量:

$data = $this->member->get_fields(array(
    Member::FIRST_NAME, Member::LAST_NAME, Member::EMAIL, Member::DISPLAY_NAME
));

这样我就可以遍历返回的数据了。

foreach ($data as $key=>$value) // ...

并设置字段...

$this->member->set_fields(array(
    Member::FIRST_NAME => $first_name,   //  THE BIG ADVANTAGE HERE:
    Member::LAST_NAME => $last_name,     //  These field keys auto-complete
    Member::EMAIL => $email,             //  so you don't have to remember them!
    Member::DISPLAY_NAME => $display_name,
    // etc...
));

还在想这个……有什么想法吗?

【问题讨论】:

  • 您可能想澄清您对“沟通”的定义。你的最终目标是什么? ObjOne 实例暴露了它所拥有的 ObjTwo 实例的成员?
  • 你到底想做什么?您是否尝试将对象 A 的所有属性分配给对象 B?为什么?!
  • 为什么要将第一个对象复制到第二个?两个对象通过方法或发布/订阅策略进行通信
  • 我同意,第一遍有点误导。制作相同的副本不是目标,但通常需要传输数据的一个子集。我进行了一些编辑以反映更通用的用法。另外,我添加了一个我正在考虑实施的答案,对任何意见都感兴趣。
  • 整个映射思路是错误的,你不需要这样做。使用常量也不是一个好主意,a)因为不需要整个东西,b)因为常量就是它们......而不是变量。

标签: php oop


【解决方案1】:

我认为你问错了问题。此外,我认为只有提供 真实 示例而不是那些伪示例,才能真正提供帮助。对于正确的解决方案,每种实际情况都不同。

一般来说,您的所有提案都很有味道。看来你需要的不是注入而是继承。如果您的“子”类确实需要访问另一个类的全部或大部分属性,那么它似乎应该扩展该类。

您的软件的各个部分应该尽可能少地相互了解。在您的评论中,您提到您有一个 Member 类和一个 Form 类。我不知道为什么他们中的任何一个都应该知道对方的任何事情。

此外,您似乎认为您需要将每个属性映射到新类中的一个属性。为什么?如果您通过 custructor(= 依赖注入)将一个类的实例传递给另一个类,那么您可以将该实例映射到一个属性,然后通过该实例访问注入实例的所有属性。无需映射。

class Consumer
{
    private $injectedClass;

    function __construct($injectedClass)
    {
        $this->injectedClass = $injectedClass;
    }

    public function someFunction()
    {
        //do something by using any property of the injected class
        $this->injectedClass->getProperty();
    }
}

【讨论】:

  • 现在,我正在使用 Member 类和 Form 类,虽然我开始扩展到许多其他类类型,并且在未来我将拥有更多不同的结构。所以,我的问题很笼统:-\。请参阅我刚刚添加的答案,我对您的意见很感兴趣。
  • 发布您的成员类和表单类的重要部分,并告诉我们,您认为彼此需要了解哪些属性以及原因。
【解决方案2】:

我倾向于这样做。这可能不是最好的方法:

class Parent_Obj {
    $var1; // explanation
    $var2; // explanation
    $var3; // explanation
    $child_obj; // explanation

    __construction() {
        /* Do a bunch of stuff */
        $this->$child_obj = new Child_Obj ($this);
    }
}

class Child_Obj {
    $var1; // explanation
    $var2; // explanation
    $var3; // explanation
    $parent_obj; // explanation

    __construction($parent) {
        /* Do a bunch of stuff */
        $this->$parent_obj = $parent;
    }

    /* Some function that needs a method or property of the parent object */
    function some_function () { 
        /* do some stuff */
        echo $this->parent_obj->var1; // echo a property of the parent obj
    }
}

我相信这方面的术语称为“聚合”。

【讨论】:

  • IMO 这不是一个好方法。它创建了必须避免的循环依赖!
猜你喜欢
  • 2013-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-12
  • 2012-08-30
  • 1970-01-01
  • 2011-07-06
  • 1970-01-01
相关资源
最近更新 更多