我有三门课:
- 数据库
- 用户
- 页面
每个都按其暗示进行。
因此,用户和页面都需要连接到数据库以获取其数据(用户信息、页面内容) - 它们都通过依赖关系访问数据库从数据库注入(inject),这完全没问题。但是,页面还需要显示用户获取的数据。
这会成为问题,因为如果我将用户注入(inject)页面,技术上不会提示页面有两个 数据库的实例,既是它自己的,也是存在于 User 中的?这不是一个好的做法,对吗?
据我所知,在这种情况下“扩展”也不是正确的解决方案。 页面与用户没有直接关系,因此它们不必成为一个。
所以,我有两个问题:
- 通过将User注入(inject)Page,将注入(inject)User的数据库对象引导至Page是否“正确”?强>?
- 如果不是,正确的方法是什么?
最佳答案
我认为您对引用文献的工作方式存在一些误解。假设我创建了一个数据库对象:
class Database {
function talkToDb(){
//does some database stuff
}
}
现在,假设我想要一个 User
类来访问 Database
对象 - 大概用于读取和写入持久层:
class User {
persistence = null; //This 'points' to a database object that is injected on object instantiation.
function __construct(Database $db) {
$this->persistence = db;
}
}
要创建用户
,您需要在代码中的某处执行以下操作:
$db = new Database();
$aUser = new User($db);
$bUser = new User($db);
此时$aUser
和$bUser
使用相同 Database
对象。让我们来谈谈 Page
:它的实例化与 User
出奇地相似:
class Page {
$persistence = null;
$someUser = null;
function __construct(Database $db, User $user) {
$this->persistence = $db;
$this->someUser = $user;
}
}
然后,您将再次在代码中的其他位置创建 Page
类。就像这样:
$db = new Database();
$aUser = new User($db);
$aPage = new Page($db, $aUser);
此时,$aUser
和 $aPage
中的对象字段都指向< Strong>same Database
对象:一个命名 $db
(至少,它是在我们的范围内命名的)在上面创建它)。 $aPage
还保存对$aUser
的引用。因为它有两个引用 - 一个指向用户,一个指向数据库 - 它理论上可以通过两种方式访问相同数据库对象:
class Page {
... //construct everything as above
function accessExample() {
//The following two lines call the exact same function on the exact same object
$this->persistance->talkToDb();
$this->someUser->persistance->talkToDb();
}
}
请记住:当您将一个对象“注入(inject)”到另外两个对象中时,您并不是在复制该对象,而是只是复制对该对象的引用。对于许多对象来说,保存同一引用的副本是合适的。
您可以以任何一种方式访问数据库这一事实并不意味着您应该这样做。您可以通过将用户
的数据库设为私有(private)来从页面
中屏蔽该数据库。也就是说,不这样做只是代码整洁的问题:您仍然可以。
请注意,相互“扩展”Page
或 User
或从数据库“扩展”完全不合适
.扩展类实际上是前一个类的“子集”或“更具体的形式”。 User
不是 Database
的特殊形式:MySqlDatabase
是。相反,我们知道用户
需要有一个可以“持久”其状态的数据库。这就是为什么我们为它提供对某个Database
对象的“引用”。我们应该为需要访问同一数据库的所有此类对象提供相同的引用。许多对象可能持有对同一数据库对象的引用这一事实并不重要:为什么这会导致问题?
(买者自负:我实际上并没有运行上述代码,因此可能存在小错误。)
关于PHP - 如何组合三个或更多相互依赖的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28930899/