gpt4 book ai didi

language-agnostic - 依赖注入(inject)、延迟加载、代理和循环依赖

转载 作者:行者123 更新时间:2023-12-02 03:47:45 25 4
gpt4 key购买 nike

这是一个与语言无关的问题,但我用 PHP 编写示例代码。

我们有两个类:

  1. 用户
  2. UserRepository

UserRepository 类处理与数据库的交互并将所需的用户加载到用户对象中并返回它。

假设在 User 类中有一个 email 属性最初没有加载,它会在需要时从数据库中延迟加载。但是 User 类不应该知道 UserRepository 类,所以我们在这里创建一个电子邮件代理。它知道 UserRepository,如果需要电子邮件,它会从 UserRepository 中询问。

到目前为止,这是代码:

用户类

class User
{
private $username;
private $email_proxy;
public function __construct($username,EmailProxy $email_proxy)
{
$this->username = $username;
$this->email_proxy = $email_proxy;
}

public function get_username()
{
return $this->username;
}

public function get_email()
{
return $this->email_proxy->get_email($this->get_username());
}
}

UserRepository 类

class UserRepository
{
private $db;
public function __construct($db)
{
$this->db = $db;
}

/**
* @param string username
* @return string email , email address of the user
*/
public function get_email_by_username($username)
{
// interaction with DB, ...
return $user_email;
}
}

电子邮件代理类

class EmailProxy
{
private $user_repository;
public function __construct(UserRepository $repository)
{
$this->user_repository = $repository;
}
public function get_email($username)
{
return $this->user_repository->get_email_by_username($username);
}
}

这是使用示例:

$user_repository = new UserRepository($db_instance);
$email_proxy = new EmailProxy();
$user = new User('my_username', $email_proxy);

到目前为止一切顺利。但这是我需要你帮助的棘手部分。从本质上讲,UserRepository 应该负责从 DataBase 中获取 User 对象,构造一个 User 对象并返回它。如下所示:

class UserRepository
{
private $db;
public function __construct($db)
{
$this->db = $db;
}

public function get_email_by_username($username)
{
// interaction with DB, ...
return $user_email;
}

public function get_user_by_username($username)
{
// fetch the User from DB and ...
return new User($fetched_username) // missing the EmailProxy
}
}

所以我的问题是如何将 EmailProxy 传递给 UserRepository 创建的 User 对象?

  • 您是否将 UserProxy 实例注入(inject)到 UserRepository 以便将其注入(inject)到新创建的 User 对象中?

  • 您会为此使用依赖注入(inject)容器吗?

  • 你会使用工厂吗?

编辑

EmailProxy is already aware of UserRepository, if we pass EmailProxy to UserRepository as well, it would be a circular dependency.

任何代码/评论将不胜感激。

谢谢,

最佳答案

这是一个棘手的问题,我很想听听人们是如何处理它的。与此同时,这就是我自己的想法。

我会将 UserUserRepository 类的创建放在工厂中

class ServiceFactory
{
private $instances=[];
public function createUser($data)
{
return new User($data)
->setEmailProxy($this->createEmailProxy());

}

public function createEmailProxy()
{
if (!isset($this->instances['EmailProxy'])) {
$this->instances['EmailProxy'] = new EmailProxy(
$this->createUserRepository()
);
}
return $this->instances['EmailProxy'];
}

public function createUserRepository()
{
if (!isset($this->instances['UserRepository'])) {
$this->instances['UserRepository'] = new UserRepository(
$db,
$this->createDtoFactory()
);
}
return $this->instances['UserRepository'];
}

public function createDtoProvider()
{
return new DtoProvider($this);
}

}

这是DtoProvider类的代码

class DtoProvider
{
private $serviceFactory;

public function __construct($factory)
{
$this->serviceFactory = $factory;
}

public function createUser($data)
{
return $this->serviceFactory->createUser($data);
}

public function createOtherStuff($data)
{
return $this->serviceFactory->createOtherStuff($data);
}
}

这个类的目的是从服务中隐藏工厂。您只提供他们需要的东西。

现在您的 UserRepository 应该看起来像这样

class UserRepository
{
private $db;
private $services;
public function __construct($db, $serviceProvider)
{
$this->db = $db;
$this->services = $serviceProvider;
}

public function get_email_by_username($username)
{
// interaction with DB, ...
return $user_email;
}

public function get_user_by_username($username)
{
// fetch the User from DB and ...
return $this->services->createUser($data)
}
}

这似乎有点矫枉过正(而且很可能是这样),但它允许您很容易地重构代码,这对长期应用很有好处。

我想这完全取决于您喜欢易于阅读的代码还是易于(快速)编写的代码。

关于language-agnostic - 依赖注入(inject)、延迟加载、代理和循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15821213/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com