构造函数替代此方案

时间:2013-08-27 16:49:39

标签: php oop design-patterns

我有一个包含很多类方法中使用的私有属性的类:

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

consructor获取模型的id,然后尝试从该id实例化模型。该模型被设置为属性,然后在所有其他类方法中使用。

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

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

1 个答案:

答案 0 :(得分:1)

在这种情况下,您将描述我将使用依赖注入(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

如果两个属性对象具有相同的metod并不重要 如果他们不实现相同的界面。这样就迫使客户使用MyClass预期使用的方式,从不担心传递对象无法使用的错误参数。

当然,由客户端使用您的类来正确检查对象,因此不会发生错误:

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