Php 创建具有多(多)个参数的对象的最佳实践(构造函数vs setter)?

Php 创建具有多(多)个参数的对象的最佳实践(构造函数vs setter)?,php,object,constructor,setter,Php,Object,Constructor,Setter,我的代码库中有相当多的POPO(普通的旧PHP对象),其中一些包含超过30个字段。其中一些对象有许多必填字段,以及许多可选字段(其中一些设置了默认值) 以下是其中一个类的简化版本: Class POPO { private $required; private $alsoRequired; private $defaultSet = 100; private $optional; private $alsoOptional; public fu

我的代码库中有相当多的POPO(普通的旧PHP对象),其中一些包含超过30个字段。其中一些对象有许多必填字段,以及许多可选字段(其中一些设置了默认值)

以下是其中一个类的简化版本:

Class POPO  {
    private $required;
    private $alsoRequired;
    private $defaultSet = 100;
    private $optional;
    private $alsoOptional;

    public function __construct()  {
        //some constructor code
    }

    public function setRequired($required)  {
        //validate here
        $this->required = $required;
    }

    //other setters
    ...
}
我的问题是关于最佳实践。对于实例化对象和设置值,我有两个选项:

  • 我可以创建一个包含非必填字段默认值的构造函数,并对可选内容使用setter:

    public function __construct(
        $required,
        $alsoRequired
    )  {
        $this->setRequired(1);
        $this->setAlsoRequired(2);
    }
    
    $POPO1 = new POPO(1,2);  //to instanciate new object w/ only required fields.
    $POPO1->setOptional(3);  //to set optional fields
    
  • 我可以使用可选参数创建包含所有字段的构造函数:

    public function __construct(
        $required,
        $alsoRequired,
        $optional = null,
        $alsoOptional = null
    )  {
        $this->setRequired($required);
        $this->setAlsoRequired($alsoRequired);
        $this->setOptional($optional);
        $this->setAlsoOptional($alsoOptional);
    }
    
    $POPO1 = newPOPO(1,2);  //instanciate new object w/ only required fields.
    $POPO2 = newPOPO(1,2,3,4);  //instanciate object w/ optional fields.
    
  • 在类中添加或删除参数时,这会让人感到困惑。必须更新使用该类的每个实例。选项1也是如此,但程度较低

    我遇到了第三个选项,它有一个无参数构造函数,并对所有内容使用setter,但这将允许对象处于无效状态

    所以我的问题是,这两个选项中哪一个更好

    也许还有一种更好的方式我没有想到

    处理默认值怎么样?这应该只通过setter完成吗

    在类中添加或删除参数时,这会让人感到困惑

    类应为扩展打开,但为修改关闭-

    一个更干净的方法可以是。您可以选择使用两个单独的数组—一个用于必需属性,另一个用于可选属性

    此外,如果需要,也可以使用

    所以我的问题是,这两个选项中哪一个更好

    若您有太多的参数,选项1(构造函数中的必需值,setters中的可选值)将更具可读性

    我想到的第三个选项是使用无参数构造函数并对所有内容使用setter,但这将允许 对象将处于无效状态

    我不建议在代码中的任何时候让对象处于无效状态

    也许还有一种更好的方式我没有想到`

    类POPO
    {
    受保护的$conf;
    公共函数构造(PopoConfiguration$conf)
    {
    $this->conf=$conf;
    }
    //从现在开始,使用$this->conf getters
    }
    类popo配置
    {
    所需受保护美元;
    还需要受保护的美元;
    受保护的$defaultSet=100;
    受保护的美元可选;
    受保护的$alsoOptional;
    公共函数构造(/*必需参数*/)
    {
    // ...
    }
    //接球手和接球手
    }
    $popoConf=新的PopoConfiguration();
    //在这里操作您的配置
    $popoConf->setAlsoOptional(42);
    // ...
    //实例化POPO
    $popo=新popo($popoConf);
    
    • 所有必需的参数在技术上都是必需的(在PopoConfiguration的构造函数中)
    • 可以在实例化新POPO之前设置所有可选参数
    • 一旦您实例化一个新的POPO,它将被完全配置并处于可用状态
    • 该代码是可测试的
    • 一个类只负责设置值(可能带有某种形式的验证),一个类只负责设置值 负责POPOing(无论是什么)。这将使它们内部的业务逻辑更加清晰
    一个好的实践是尽可能地记录POPO配置,这样任何人都可以确切地知道他们可以(和不能)做什么来配置POPO对象

    处理默认值怎么样?这应该只通过setter完成吗


    如果有很多参数(参数的数量会影响可读性),最好只通过setter进行设置。

    方法1听起来不错。使用关联数组传递可选属性非常有效。这减少了必须调用的函数的数量。我现在也遇到了同样的问题。需要具有许多字段和其中一些字段(可能很多字段)的普通对象。没有更多的答案或评论?