ソフトウェア工学を学ぶなかで、クラス図描いたらプログラムの関係が整理できて素敵じゃん!やってみよう!と思いますよね。でも描き始めたら、

関連と集約の違いがわからなくてモヤモヤする。んー、やめようかな。別にクラス図描きたかったわけじゃないし。プログラム描きたかったんだし。

わかならい用語多くてモヤモヤするよね!
抽象的な説明だと、どちらも同じでは?と疑問が残ります。
そこでこの記事では、なるべく多くの方に関連と集約の違いを伝えられるように、日本語、PlantUML、Pythonを使って丁寧に説明します。あなたのクラス図への熱量が冷めないうちに。
概要
クラス同士が関連し合うとき、条件が増えるごとに呼び方が変わります。関連は柔軟な関係で、クラス間の入れ替えが比較的簡単。集約はもうすこし構造的な関係で、部分を入替えるときに全体を見直して整合をとる必要があり、クラスの入れ替えが比較的難しい。
| 関連 | 集約 | 合成集約 | |
| 記号 | ーー | ー◇ | ー◆ |
| 生存期間 | 管理しない | 管理する | 完全に管理する |
| クラスの結びつき | 弱い | 強い | より強い |

関連(Association)
関連は、単純に一方のクラスが他方のクラスのメソッドを使ったり、データを参照したりすることを表しています。使っているだけですので、使用するクラスを変更することが比較的簡単な関係にあります。
たとえば、魔法使いの学校で、ある魔法使いが杖を借りている場面を考えてみましょう。登場人物は、Wizardクラス(魔法使い)とStaffクラス(杖)です。魔法使いは、杖を借りただけですので、使い終わったら、返却します。また、次の日、複数ある杖の中から別の杖を選んで借りても問題ありません。このような、比較的ゆるい関係のことを、関連と表しています。
Wizardクラス(魔法使い)は、Staffクラス(杖)を使っているだけで、所有しているわけではないことに注意してください。つまり、Wizardクラス(魔法使い)にとって、特定のStaffクラス(杖)が必要なわけではありません。たまたま見つけた杖を使っているのです。
クラス図でみる関連
関連のクラス図の例を下図で示します。リンク記号で関連を表しています。
@startuml
class Wizard {
name : String
castSpell() : void
}
class Staff {
material : String
castMagic() : void
}
Wizard "1" o-- "1" Staff : owns
@endumlPythonでみる関連
関連のPythonスクリプトの例は、次のとおりです。このプログラムでは、WizardクラスとStaffクラスの生存期間は無関係になっています。もし、魔法使い(Wizardクラス)が敵に倒されても、杖(Staffクラス)は生き残ります。
class Staff:
def __init__(self, spell_name):
self.spell_name = spell_name
def cast_spell(self):
print(f"Casting {self.spell_name}!")
class Wizard:
def __init__(self, name):
self.name = name
self.staffs = []
def use_magic(self):
if not self.staffs:
print(f"{self.name} has no staff to cast spells with!")
else:
print(f"{self.name} starts casting spells with their staffs:")
for staff in self.staffs:
staff.cast_spell()
def add_staff(self, staff):
self.staffs.append(staff)
print(f"{self.name} has acquired a new staff for casting {staff.spell_name}.")
# Create a wizard
wizard = Wizard("Gandalf")
# Create staffs
fire_staff = Staff("Fireball")
ice_staff = Staff("Ice Blast")
# Add staffs to the wizard
wizard.add_staff(fire_staff)
wizard.add_staff(ice_staff)
# Wizard uses magic
wizard.use_magic()
集約(Aggregation)
クラス図でみる集約
@startuml
class AdventureParty {
addMember()
removeMember()
}
class Wizard {
useMagic()
}
AdventureParty o-- "0..*" Wizard
@endumlPythonでみる集約
class Wizard:
def __init__(self, name):
self.name = name
def use_magic(self):
print(f"{self.name} uses magic!")
class AdventureParty:
def __init__(self):
self.members = []
def add_member(self, wizard):
if wizard not in self.members:
self.members.append(wizard)
print(f"{wizard.name} has been added to the party.")
else:
print(f"{wizard.name} is already a member of the party.")
def remove_member(self, wizard):
if wizard in self.members:
self.members.remove(wizard)
print(f"{wizard.name} has been removed from the party.")
else:
print(f"{wizard.name} is not a member of the party.")
# 魔法使いのインスタンスを作成
wizard1 = Wizard("Gandalf")
wizard2 = Wizard("Saruman")
# 冒険者パーティーのインスタンスを作成
party = AdventureParty()
# パーティーに魔法使いを追加
party.add_member(wizard1)
party.add_member(wizard2)
# 魔法使いが魔法を使う
wizard1.use_magic()
wizard2.use_magic()
# パーティーから魔法使いを削除
party.remove_member(wizard1)

コメント