我正在閱讀一篇關于 OOP、關聯、組合、聚合等關系的文章。有些東西令人困惑,我一直在網上找到相互矛盾的資訊,所以我希望有人能對此有所了解。
因此,在 PHP 中,我們將以下代碼組合稱為代碼組合,并且很多文章/教程都指出使用組合而不是繼承。
class A
{
}
class B
{
public function __construct(protected A $a)
{
}
}
在閱讀了幾篇關于組合和聚合的文章后,似乎上面實際上是聚合而不是組合的示例,因為在組合中A類的物件沒有B類就不能存在,所以當B類的物件被銷毀時A級的也應該被銷毀。在上面的代碼中顯然不是這樣,因為 A 類的物件可以存在于 B 類之外,所以它的生命周期不依賴于 B 類。
以下是組合的示例:
class B
{
public A $a;
public function __construct()
{
$this->a = new A();
}
}
因此,根據我的理解,聚合意味著 A 類的物件可以存在于 B 類之外,而組合意味著 A 類的生命周期物件依賴于 B 類,并且不能存在于 B 類之外。
我是否正確理解這一點?
uj5u.com熱心網友回復:
重要的是要記住,這些是關聯類和物件的模式。
我要說的第一點是,任何諸如“使用組合而不是繼承”之類的一攬子規則都反映了一些缺失的背景關系。如果合適,請使用繼承。
這些其他模式用于將類關聯在一起。
聚合通常用于層次/父/子關系。
一個典型的例子是關聯員工和部門。
- Employee 物件存在
- 員工是部門“擁有/成員”
- 您可以說“Department Foo”聚合了 0-N 名員工。
因此,為了對此建模,Department 通常會有一個內部 employees[] 陣列。
相反,員工可以在內部存盤部門物件。這基本上匹配了兩個類之間的關系,即 Many >-< Many。
組合反映了更嚴格的父/子關系,這意味著 ObjectA 由 1-N 個物件 B 組成。
組合關系的經典示例是購物車,其中包含 0-N 個產品線項。
假設 Cart 和 Lineitem 的類,Cart 將存盤 Lineitem 陣列。
Aggregation 和 Composition 之間的主要區別在于,如果Cart 被銷毀,則使用 Composition ,則所有關聯的 Lineitem 物件都應該被銷毀。
在聚合示例中,如果一個部門被洗掉,這并不一定意味著所有聚合的員工都會被洗掉,而是一個部門的洗掉只會破壞員工與部門之間的關系,并且可能需要存盤一個部門的變數員工的部門物件將為空,直到員工被分配到另一個部門,或者他們的作業結束。
實際上,由于 PHP 是頁面范圍的,因此變數和物件組合是短暫的,所以在 ORM 之外,您并沒有真正找到很多使用這些 UML 模式的案例。資料需要被持久化,通常這種持久化是通過某種 RDBMS 或檔案資料庫,其中 ORM 將模擬表之間的關系,或者可能是層次結構。
對于您的示例:
這類 foo/bar A/B 示例沒有語意意義或價值。示例 #1 中的唯一機制是,如果 ObjB 首先是 ObjA,就無法構建它們。您提供的語法是 PHP8 中的新語法,起初我錯過了。
這個例子似乎更可能需要:
class A
{
private bSet = array();
public function addB(B $b) {
$this->bSet[] = new B($this);
}
}
class B
{
private $a;
public function __construct(A $a)
{
$this->a = $a;
}
}
// B shouldn't be made without a Parent A
$objA = new A();
$objA->addB();
$objA->addB();
但是,從技術上講,沒有什么可以阻止您制作 B,因為建構式始終是公開的。
$objB = new B($objA);
使用聚合,這將是一種更可能的情況:
class A
{
private bSet = array();
public function addB(B $b) {
$this->bSet[] = $b;
$b->setA($this);
}
public function delB(B $b) {
for ($i=0; $i < count($this->bSet); $i ) {
if ($b === $this->bSet[$i]) {
unset($this->bSet[$i];
break;
}
}
}
}
class B
{
private $a;
public function setA(A $a) {
if ($this->a) {
$this->a->delB($this);
}
$this->a = $a;
}
public function getA() {
return $this->a;
}
}
$objA1 = new A();
$objA2 = new A();
$objB1 = new B();
$objB2 = new B();
$objB3 = new B();
$objA1->addB($objB2);
$objA2->addB($objB1);
$objA2->addB($objB3);
//Change $objB3's parent from A1 to A2.
$objB3->setA($objA1);
A 和 B 相互獨立,但仍具有所有權。
我發現在 PHP 開發中更實際有價值的是依賴注入作為領先 PHP 框架(Symfony、Laravel)的基礎,以及您在Gang of 4 書籍、領域驅動設計或其他中找到的其他常見 OOP 設計模式的實作這些天來的書籍和網站。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/418005.html
標籤:
