处理对象依赖

Handling Object Dependency

考虑以下 class

class User
{
    protected $password;

    public function setPassword($password)
    {
        $this->password = $password;
        return $this;
    }

    public function getPassword()
    {
        return $this->password;
    }
}

我想在用户对象中使用 Zend\Crypt\Password\Bcrypt 对密码应用 bcrypt,因为这会产生依赖性我想知道如何正确处理这个问题,我可以考虑几种方法来完成这项工作,让我详细说明

方法 1:这里我们在方法中实例化 class 并应用所需的更改。

class User
{
    protected $password;

    public function setPassword($password)
    {
        $bcrypt = new Bcrypt();
        $this->password = $bcrypt->create($password);
        return $this;
    }

    public function getPassword()
    {
        return $this->password;
    }

    public function verifyPassword($password)
    {
        $bcrypt = new Bcrypt();
        return $bcrypt->verify($password, $this->getPassword());
    }
}

根据我的理解,这不是推荐的方法,因为我在这里看到两个问题

  1. Bcrypt() 被实例化了两次
  2. 这使得 User 对象与 Bcrypt 紧密耦合

我可以通过在 class 构造函数中实例化一次 Bcrypt() 并在需要时使用它来解决问题 1,但这并不能解决问题 2

方法 2: 将 Bcrypt 对象移出用户 class 并在设置密码时注入它

class User
{
    protected $password;

    public function setPassword($password)
    {
        $this->password = $password;    
        return $this;
    }

    public function getPassword()
    {
        return $this->password;
    }
}

// Init Bcrypt
$bcrypt = new Bcrypt;

// Instantiate user object and create a password
$user = new User;
$user->setPassword($bcrypt->create($password));

// Verify user password
if ($bcrypt->verify($password, $user->getPassword())) {
    // Password is verified
}

最好的解决方法是什么?

谢谢。

我想第一种方法更好,因为它 隐藏 在用户 class.

中使用 bcrypt

我不认为其他程序员必须记住他在使用 User class.

时必须使用,例如,$bcrypt->verify

也许您可以创建一个密码 class 并将此逻辑移到那里? 您可以这样做:

class Password
{
    private $password;
    public __construct($password)
    {
        $this->password = $password;
    }

    public crypt(Zend_Crypt_Password_PasswordInterface $crypt)
    {
        $this->password = $crypt->create($password);
    }
}

或使用 Decorator。 这两种解决方案都为您提供了扩展代码的可能性。 除了 Zend_Crypt_Password_PasswordInterface,您还可以使用自己的 Wrapper。恕我直言,这将是更好的解决方案。

然后您可以为特定用户设置密码,它不关心它是否被加密、散列或其他:

class User
{
    private $password;

    public function changePassword(Password $password)
    {
        $this->password = $password;
    }
}