Php 此场景的构造函数替代方案

Php 此场景的构造函数替代方案,php,oop,design-patterns,Php,Oop,Design Patterns,我有一个类,它包含一个私有属性,在许多类和方法中使用: class MyClass { private $_myProperty; public function __construct($myPropertyId) { $this->_initMyPropertyModel($myPropertyId); } public function initMyPropertyModel() { $this-&

我有一个类,它包含一个私有属性,在许多类和方法中使用:

class MyClass
{
    private $_myProperty;

    public function __construct($myPropertyId)
    {
         $this->_initMyPropertyModel($myPropertyId);
    }

    public function initMyPropertyModel()
    {
        $this->_myProperty = new MyProperty($this->_myPropertyId);
    }

    public function methodA()
    {
        // do stuff with $this->_myProperty;
    }

    public function methodA()
    {
        // do stuff with $this->_myProperty;
    }

    public function methodC()
    {
        // do stuff with $this->_myProperty;
    }
}
构造函数获取模型的id,然后尝试从该id实例化模型。该模型被设置为属性,然后在所有其他类方法中使用

这样做的问题是,模型的建立可能会出错,并且模型没有正确实例化,因此在使用它的每个方法中都存在潜在的问题

有没有更好的方法来处理此代码?我看到的另外两个选择是: 1.强制客户端传递创建的模型而不是id 2.在使用模型的每个方法中检查null
3.如果未正确实例化,则从构造函数中抛出异常,但我认为这一点都不可取。

在您描述的这个场景中,我将使用依赖项注入(DI),因此代码可能更灵活、可管理和稳定。
基本上,方法A、B和C依赖于适当的属性模型,因此应避免检查null。
抛出异常总是一个好的选择,因为它解释了什么是错误的

使用DI而不是通过构造函数和/或负责创建适当模型(紧密耦合)的initMyPropertyModel()方法创建类,外部进程应该对此负责构造函数应仅依赖于模型接口

class MyClass {
    // do not use private visibility unless you are sure it really needs to be private
    protected $_myProperty;

    // we dont care about the concrete object as long as it follows the required interface
    public function __construct(MyPropertyInterface $property) 
    {
        $this->_myProperty = $property;
        $this->_myProperty->initProperty(); // thanks to interface, MyClass can be sure this method can be called!
    }
    //... more class code
}

interface MyPropertyInterface
{
    public function initProperty();
}

class MyProperty implements MyPropertyInterface
{
    public function initProperty()
    {
        echo 'MyProperty initiated!';
    }
}
class MyProperty2
{
    public function initProperty()
    {
        echo 'MyProperty initiated!';
    }
}
用法示例:

$myObj = new MyClass(new MyProperty()); // works
$myObj2 = new MyClass(new MyProperty2()); // Catchable fatal error
如果两个属性对象具有相同的方法,这并不重要 如果它们没有实现相同的接口。通过这种方式,您可以强制客户机按预期的方式使用
MyClass
,而不必担心传递对象无法使用的错误参数

当然,由使用您的类的客户端来正确检查对象,以避免出现错误:

$prop2 = new MyProperty2();
if ($prop2 instanceof MyPropertyInterface) {
    $myObj2 = new MyClass(new MyProperty2());
} else {
    // throw exception, show error, w/e
}