组合(如果你移除“整体”,“部分”也会自动被移除--“拥有关系”)
在新类内创建现有类的对象。这被称为组合,因为新类由现有类的对象组成。
通常使用普通成员变量。
如果组合类自动处理子类的创建/销毁责任,则可以使用指针值。
C++ 中的组合
#include <iostream>
using namespace std;
/********************** Engine Class ******************/
class Engine
{
int nEngineNumber;
public:
Engine(int nEngineNo);
~Engine(void);
};
Engine::Engine(int nEngineNo)
{
cout<<" Engine :: Constructor " <<endl;
}
Engine::~Engine(void)
{
cout<<" Engine :: Destructor " <<endl;
}
/********************** Car Class ******************/
class Car
{
int nCarColorNumber;
int nCarModelNumber;
Engine objEngine;
public:
Car (int, int,int);
~Car(void);
};
Car::Car(int nModelNo,int nColorNo, int nEngineNo):
nCarModelNumber(nModelNo),nCarColorNumber(nColorNo),objEngine(nEngineNo)
{
cout<<" Car :: Constructor " <<endl;
}
Car::~Car(void)
{
cout<<" Car :: Destructor " <<endl;
Car
Engine
Figure 1 : Composition
}
/********************** Bus Class ******************/
class Bus
{
int nBusColorNumber;
int nBusModelNumber;
Engine* ptrEngine;
public:
Bus(int,int,int);
~Bus(void);
};
Bus::Bus(int nModelNo,int nColorNo, int nEngineNo):
nBusModelNumber(nModelNo),nBusColorNumber(nColorNo)
{
ptrEngine = new Engine(nEngineNo);
cout<<" Bus :: Constructor " <<endl;
}
Bus::~Bus(void)
{
cout<<" Bus :: Destructor " <<endl;
delete ptrEngine;
}
/********************** Main Function ******************/
int main()
{
freopen ("InstallationDump.Log", "w", stdout);
cout<<"--------------- Start Of Program --------------------"<<endl;
// Composition using simple Engine in a car object
{
cout<<"------------- Inside Car Block ------------------"<<endl;
Car objCar (1, 2,3);
}
cout<<"------------- Out of Car Block ------------------"<<endl;
// Composition using pointer of Engine in a Bus object
{
cout<<"------------- Inside Bus Block ------------------"<<endl;
Bus objBus(11, 22,33);
}
cout<<"------------- Out of Bus Block ------------------"<<endl;
cout<<"--------------- End Of Program --------------------"<<endl;
fclose (stdout);
}
输出
--------------- Start Of Program --------------------
------------- Inside Car Block ------------------
Engine :: Constructor
Car :: Constructor
Car :: Destructor
Engine :: Destructor
------------- Out of Car Block ------------------
------------- Inside Bus Block ------------------
Engine :: Constructor
Bus :: Constructor
Bus :: Destructor
Engine :: Destructor
------------- Out of Bus Block ------------------
--------------- End Of Program --------------------
聚合(如果去掉“整个”,“部分”仍然存在-“没有所有权”)
聚合是一种特定类型的组合,其中复杂对象和子对象之间没有所有权关系。当聚合被销毁时,子对象不会被销毁。
通常使用指向生存于聚合类范围外的对象的指针变量/引用变量
可以使用指向生存于聚合类范围外的对象的引用值
不负责创建/销毁子类
C++中的聚合代码
#include <iostream>
#include <string>
using namespace std;
/********************** Teacher Class ******************/
class Teacher
{
private:
string m_strName;
public:
Teacher(string strName);
~Teacher(void);
string GetName();
};
Teacher::Teacher(string strName) : m_strName(strName)
{
cout<<" Teacher :: Constructor --- Teacher Name :: "<<m_strName<<endl;
}
Teacher::~Teacher(void)
{
cout<<" Teacher :: Destructor --- Teacher Name :: "<<m_strName<<endl;
}
string Teacher::GetName()
{
return m_strName;
}
/********************** Department Class ******************/
class Department
{
private:
Teacher *m_pcTeacher;
Teacher& m_refTeacher;
public:
Department(Teacher *pcTeacher, Teacher& objTeacher);
~Department(void);
};
Department::Department(Teacher *pcTeacher, Teacher& objTeacher)
: m_pcTeacher(pcTeacher), m_refTeacher(objTeacher)
{
cout<<" Department :: Constructor " <<endl;
}
Department::~Department(void)
{
cout<<" Department :: Destructor " <<endl;
}
/********************** Main Function ******************/
int main()
{
freopen ("InstallationDump.Log", "w", stdout);
cout<<"--------------- Start Of Program --------------------"<<endl;
{
// Create a teacher outside the scope of the Department
Teacher objTeacher("Reference Teacher");
Teacher *pTeacher = new Teacher("Pointer Teacher"); // create a teacher
{
cout<<"------------- Inside Block ------------------"<<endl;
// Create a department and use the constructor parameter to pass the teacher to it.
Department cDept(pTeacher,objTeacher);
Department
Teacher
Figure 2: Aggregation
} // cDept goes out of scope here and is destroyed
cout<<"------------- Out of Block ------------------"<<endl;
// pTeacher still exists here because cDept did not destroy it
delete pTeacher;
}
cout<<"--------------- End Of Program --------------------"<<endl;
fclose (stdout);
}
--------------- Start Of Program --------------------
Teacher :: Constructor --- Teacher Name :: Reference Teacher
Teacher :: Constructor --- Teacher Name :: Pointer Teacher
------------- Inside Block ------------------
Department :: Constructor
Department :: Destructor
------------- Out of Block ------------------
Teacher :: Destructor --- Teacher Name :: Pointer Teacher
Teacher :: Destructor --- Teacher Name :: Reference Teacher
--------------- End Of Program --------------------
https://www.linkedin.com/pulse/types-relationships-object-oriented-programming-oop-sarah-el-dawody/
组合(Composition):是一种“部分-整体”的关系。
例如,“发动机是汽车的一部分”、“心脏是身体的一部分”。
关联(Association):是一种“有一个”类型的关系。
例如,假设我们有两个类,则当这两个实体共享彼此的对象以进行某些工作时,并且在同一时间它们可以互不依赖地存在或者都具有自己的生命周期时,这两个类被称为“有一个”关系。
上面的示例显示了关联关系,因为Employee和Manager类都使用对方对象并且都有独立的生命周期。
聚合(Aggregation):基于“有一个”关系,是一种特殊形式的关联。
例如,“学生”和“地址”。每个学生都必须有一个地址,因此Student类和Address类之间的关系将是“有一个”类型的关系,但反过来则不成立。
Simple rules:
A "owns" B = Composition : B has no meaning or purpose in the system
without A
A "uses" B = Aggregation : B exists independently (conceptually) from A
A "belongs/Have" B= Association; And B exists just have a relation
Example 1:
A Company is an aggregation of Employees.
A Company is a composition of Accounts. When a Company ceases to do
business its Accounts cease to exist but its People continue to exist.
Employees have association relationship with each other.
Example 2: (very simplified)
A Text Editor owns a Buffer (composition). A Text Editor uses a File
(aggregation). When the Text Editor is closed,
the Buffer is destroyed but the File itself is not destroyed.
关联(Association)是两个不同类之间的一种关系,关联可以是任何类型,例如一对一、一对多等。它将两个完全独立的实体连接在一起。
聚合(Aggregation)是关联的一种特殊形式,是一种单向的类(或实体)之间的关系,例如钱包(Wallet)和货币(Money)类。钱包有钱,但货币不一定需要有钱包,因此这是一种单向关系。在这种关系中,如果其中一个结束,另一个可以继续存在。在我们的例子中,如果没有钱包类,也并不意味着货币类不能存在。
组合(Composition)是聚合的一种受限形式,在这种形式中,两个实体(或类)高度依赖于彼此。例如,人类(Human)和心脏(Heart)。人需要心脏才能生存,心脏需要人体才能生存。换句话说,当类(实体)相互依赖且它们的寿命相同(如果一个死亡,则另一个也会死亡)时,这就是组合。如果没有人类类存在,则心脏类没有意义。
来源:Remo H. Jansen的书“Beginning React: Learning TypeScript 2.x - Second Edition”:
我们将那些对象具有独立生命周期但没有拥有关系的关系称为关联。让我们看一个老师和学生的例子。多个学生可以与单个教师相关联,而单个学生也可以与多个教师相关联,但两者都具有独立的生命周期(两者都可以独立创建和删除)。因此,当一个老师离开学校时,我们不需要删除任何学生,当一个学生离开学校时,我们也不需要删除任何老师。
我们将那些对象具有独立生命周期,但存在所有权并且子对象不能属于另一个父对象的关系称为聚合。让我们以手机和手机电池为例。一个电池可以属于一个电话,但如果该电话停止工作,并且我们从数据库中删除它,则电话电池不会被删除,因为它可能仍然可用。因此,在聚合中,虽然存在所有权,但对象具有其生命周期。
我们使用术语组成来指代对象没有独立生命周期的关系,如果父对象被删除,所有子对象也将被删除。让我们以问题和答案之间的关系为例。单个问题可以有多个答案,并且答案不能属于多个问题。如果我们删除问题,答案将自动被删除。
组合(Composition): 这个概念是指,当你销毁一个对象(比如学校),与之绑定的另一个对象(教室)也会被一同销毁。两个对象不能独立存在。
聚合(Aggregation):
这个概念与上面(组合
)相反,当你销毁一个对象(公司
),与之绑定的另一个对象(员工
)可以独立存在。
关联(Association): 组合和聚合是关联的两种形式。
class Room < ActiveRecord::Base
belongs_to :house, required: true
end
belongs_to
关联默认创建一个composition
,子对象不能存在没有父对象的情况。因此,上面的示例可以重写为:class Room < ApplicationRecord
belongs_to :house
end
如果我们希望子对象在没有父对象的情况下存在,我们需要通过选项optional
来明确声明。
class Product < ApplicationRecord
belongs_to :category, optional: true
end