AggregationとCompositionの概念的な違いを知っています。誰かが例を挙げて、Javaでの実装の違いを教えてもらえますか?
9 に答える
構成
final class Car {
private final Engine engine;
Car(EngineSpecs specs) {
engine = new Engine(specs);
}
void move() {
engine.work();
}
}
集計
final class Car {
private Engine engine;
void setEngine(Engine engine) {
this.engine = engine;
}
void move() {
if (engine != null)
engine.work();
}
}
コンポジションの場合、Engine は Car によって完全にカプセル化されます。外の世界がエンジンへの参照を取得する方法はありません。エンジンは車と共に生き、そして死ぬ。アグリゲーションでは、車もエンジンを介してその機能を実行しますが、エンジンは常に車の内部部分であるとは限りません。エンジンを交換したり、完全に取り外したりすることもできます。それだけでなく、車内にあるかどうかに関係なく、外の世界はまだエンジンへの参照を持ち、エンジンをいじることができます。
素敵なUMLの例を使用します。
1〜20の異なる学部があり、各学部には1〜5人の教授がいる大学を考えてみましょう。大学とその学部の間には構成のつながりがあります。部門とその教授の間には集約リンクがあります。
構成は単なる強力な集合体であり、大学が破壊された場合、学部も破壊されるべきです。しかし、それぞれの学部がなくなったとしても、教授を殺すべきではありません。
Javaの場合:
public class University {
private List<Department> departments;
public void destroy(){
//it's composition, when I destroy a university I also destroy the departments. they cant live outside my university instance
if(departments!=null)
for(Department d : departments) d.destroy();
departments.clean();
departments = null;
}
}
public class Department {
private List<Professor> professors;
private University university;
Department(University univ){
this.university = univ;
//check here univ not null throw whatever depending on your needs
}
public void destroy(){
//It's aggregation here, we just tell the professor they are fired but they can still keep living
for(Professor p:professors)
p.fire(this);
professors.clean();
professors = null;
}
}
public class Professor {
private String name;
private List<Department> attachedDepartments;
public void destroy(){
}
public void fire(Department d){
attachedDepartments.remove(d);
}
}
この周りの何か。
編集:要求された例
public class Test
{
public static void main(String[] args)
{
University university = new University();
//the department only exists in the university
Department dep = university.createDepartment();
// the professor exists outside the university
Professor prof = new Professor("Raoul");
System.out.println(university.toString());
System.out.println(prof.toString());
dep.assign(prof);
System.out.println(university.toString());
System.out.println(prof.toString());
dep.destroy();
System.out.println(university.toString());
System.out.println(prof.toString());
}
}
大学の授業
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class University {
private List<Department> departments = new ArrayList<>();
public Department createDepartment() {
final Department dep = new Department(this, "Math");
departments.add(dep);
return dep;
}
public void destroy() {
System.out.println("Destroying university");
//it's composition, when I destroy a university I also destroy the departments. they cant live outside my university instance
if (departments != null)
departments.forEach(Department::destroy);
departments = null;
}
@Override
public String toString() {
return "University{\n" +
"departments=\n" + departments.stream().map(Department::toString).collect(Collectors.joining("\n")) +
"\n}";
}
}
学科クラス
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class Department {
private final String name;
private List<Professor> professors = new ArrayList<>();
private final University university;
public Department(University univ, String name) {
this.university = univ;
this.name = name;
//check here univ not null throw whatever depending on your needs
}
public void assign(Professor p) {
//maybe use a Set here
System.out.println("Department hiring " + p.getName());
professors.add(p);
p.join(this);
}
public void fire(Professor p) {
//maybe use a Set here
System.out.println("Department firing " + p.getName());
professors.remove(p);
p.quit(this);
}
public void destroy() {
//It's aggregation here, we just tell the professor they are fired but they can still keep living
System.out.println("Destroying department");
professors.forEach(professor -> professor.quit(this));
professors = null;
}
@Override
public String toString() {
return professors == null
? "Department " + name + " doesn't exists anymore"
: "Department " + name + "{\n" +
"professors=" + professors.stream().map(Professor::toString).collect(Collectors.joining("\n")) +
"\n}";
}
}
教授クラス
import java.util.ArrayList;
import java.util.List;
public class Professor {
private final String name;
private final List<Department> attachedDepartments = new ArrayList<>();
public Professor(String name) {
this.name = name;
}
public void destroy() {
}
public void join(Department d) {
attachedDepartments.add(d);
}
public void quit(Department d) {
attachedDepartments.remove(d);
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Professor " + name + " working for " + attachedDepartments.size() + " department(s)\n";
}
}
作成、採用の削除などをどのように処理する必要があるかによって異なるため、実装については議論の余地があります。OPには関係ありません。
シンプルな作曲プログラム
public class Person {
private double salary;
private String name;
private Birthday bday;
public Person(int y,int m,int d,String name){
bday=new Birthday(y, m, d);
this.name=name;
}
public double getSalary() {
return salary;
}
public String getName() {
return name;
}
public Birthday getBday() {
return bday;
}
///////////////////////////////inner class///////////////////////
private class Birthday{
int year,month,day;
public Birthday(int y,int m,int d){
year=y;
month=m;
day=d;
}
public String toString(){
return String.format("%s-%s-%s", year,month,day);
}
}
//////////////////////////////////////////////////////////////////
}
public class CompositionTst {
public static void main(String[] args) {
// TODO code application logic here
Person person=new Person(2001, 11, 29, "Thilina");
System.out.println("Name : "+person.getName());
System.out.println("Birthday : "+person.getBday());
//The below object cannot be created. A bithday cannot exixts without a Person
//Birthday bday=new Birthday(1988,11,10);
}
}
簡単な言葉で :
コンポジションとアグリゲーションはどちらもアソシエーションです。構成 -> 強い Has-A 関係 集約 -> 弱い Has-A 関係。
Aggregation
最初に、との実際の違いは何なのかについて話さなければなりませんComposition
。
アグリゲーションは、関連付けられたエンティティが関連付けから独立して存在できる関連付けです。たとえば、個人は組織に関連付けられている場合がありますが、システム内では独立して存在している場合があります。
一方
合成とは、関連付けられたエンティティの 1 つが他のエンティティと強く関連しており、他のエンティティの存在なしでは存在できない状況を指します。実際、そのエンティティの ID は、常に他のオブジェクトの ID に関連付けられています。たとえば、車の車輪。
現在、以下のように、あるエンティティのプロパティを別のエンティティに保持することで、集約を簡単に実現できます。
class Person {
Organisation worksFor;
}
class Organisation {
String name;
}
class Main {
public static void main(String args[]) {
//Create Person object independently
Person p = new Person();
//Create the Organisation independently
Organisation o = new Organisation();
o.name = "XYZ Corporation";
/*
At this point both person and organisation
exist without any association
*/
p.worksFor = o;
}
}
コンポジションの場合、依存オブジェクトは常に、関連付けられたオブジェクトの ID を使用して作成される必要があります。同じために内部クラスを使用できます。
class Car {
class Wheel {
Car associatedWith;
}
}
class Main {
public static void main() {
//Create Car object independently
Car car = new Car();
//Cannot create Wheel instance independently
//need a reference of a Car for the same.
Car.Wheel wheel = car.new Wheel();
}
}
適用シナリオによっては、同じユースケースでも集計・合成に該当する場合がありますのでご注意ください。たとえば、ある組織で働く人々のためのアプリケーションを開発していて、サインアップのために組織への参照が必須である場合、Person-Organisation のケースは合成になる可能性があります。同様に、車の部品の在庫を管理している場合、車とホイールの関係を集計することができます。
違いは、任意の構成は集約であり、その逆ではないことです。
条件を設定しましょう。Aggregation は UML 標準のメタ用語であり、単純にsharedという名前の構成と共有集計の両方を意味します。多くの場合、誤って「集合体」と名付けられています。構成も集約であるため、これは悪いことです。私が理解しているように、あなたは「共有」を意味します。
さらにUML標準から:
複合 - プロパティが複合的に集約されることを示します。つまり、複合オブジェクトは、構成されたオブジェクト (パーツ) の存在と保管に責任を持ちます。
したがって、カテドラは大学の外には存在しないため、大学からカテドラスへの協会は構成です(私見)
共有集約の正確なセマンティクスは、アプリケーション領域とモデラーによって異なります。
つまり、他のすべてのアソシエーションは、自分または他の誰かのいくつかの原則に従っているだけであれば、共有された集合体として描くことができます。こちらもご覧ください。
どちらのタイプももちろん関連付けであり、そのような言語要素に厳密にマッピングされているわけではありません。違いは、目的、コンテキスト、およびシステムのモデル化方法にあります。
実際的な例として、類似したエンティティを持つ 2 つの異なるタイプのシステムを比較します。
主に車とその所有者などを追跡する車の登録システムです。ここでは、エンジンを個別のエンティティとしては扱いませんが、出力や燃料の種類など、エンジンに関連する属性が残っている場合があります。ここで、エンジンは自動車エンティティの複合部品である場合があります。
車の部品を管理し、車にサービスを提供し、部品 (おそらく完全なエンジン) を交換するカー サービス ショップ管理システム。ここでは、エンジンの在庫があり、それらやその他の部品を車とは別に、独立して追跡する必要がある場合もあります。ここで、Engine は car エンティティの集合部分である場合があります。
言語でこれをどのように実装するかは、それほど重要ではありません。なぜなら、そのレベルでは読みやすさなどのことがはるかに重要だからです。