728x90
구현의 고려사항
- 모델과 구현 언어 간 개념의 불일치
- 모델의 분리된 뷰의 통합
- 구현의 효율성 문제
UML의 필요성
- UML은 소프트웨어 개념을 다이어그램으로 표기하기 위한 시각적인 기법(표기법)
- UML의 용도 - 문제 도메인 ,설계 제안, 구현에 관한 다이어그램을 그릴 때
- 설계를 바탕으로 코딩(구현)이 이루어진다
- UML의 클래스와 OOP(c++, JAVA, EJB)와의 관계를 이해할 필요가 있음
개념과 명세
개념 차원의 다이어그램은 추상 개념 서술 용도로 활용
→ 이 경우 다이어그램은 의미론적 규칙에 얽매이지 않음
EX) 개념 상속에서 Dog은 Animal의 특수한 경우임을 나타내는 것 이상 없음
⭐ 하지만 명세 용도의 다이어그램은 프로그램의 일부를 실제로 서술하는데 사용
→ 구현의 가이드로 사용될 경우 더 많은 부분의 정보 전달

상속 관계

C++ 은 : public, Java는 extends로 상속 관계를 표현한다!
다중상속

다중 상속(Multiple Inheritance)은 언어마다 지원 여부에 차이가 있음
- Java는 클래스 상속에서 다중 상속을 지원하지 않음
- 예시: Platypus (포유류이면서 동시에 멸종위기 동물)
Platypus는 두 상속 계층을 동시에 따름
- Mammal → Platypus
- Endangered → Platypus
💡다중상속이란?
하나의 클래스가 둘 이상의 클래스로 부터 상속 받는 것
다중상속의 표현
상속 에 따른 생성자 처리를 판단해야하는 경우 발생
- Platypus는 Mammal과 Endangered를 동시에 상속
- C++에서는 여러 부모 클래스의 생성자를 명시적으로 호출해야 함
Platypus::Platypus() : Mammal(), Endangered() {
// Platypus 초기화 코드
}
집합관계

● 개념
- 집합관계는 “전체(Whole) - 부분(Part)” (has -a, part-of)관계
- 여기서는 Polygon이 여러 개의 Point 객체를 포함함
- 전체가 없어져도 부분은 독립적으로 존재 가능→ 느슨한 관계
● UML 표현
- 빈 마름모(◇)는 Aggregation을 의미
- Polygon ↔ Point
- 1개의 Polygon은 3개 이상의 Point를 가짐 (3..*)
● 코드 예시
C++ 표현
class Polygon {
private:
Point* points[max]; // 포인터 배열로 관계 표현
};
Java 표현
public class Polygon {
private Point[] points;
public Polygon() {
points = new Point[max]; // 참조로 관계 설정
}
}
핵심 정리
언어
|
집합관계 구현 방식
|
C++
|
포인터로 Point를 참조
|
Java
|
객체 배열 또는 컬렉션으로 Point를 참조
|
집합 연관
class Person {
public:
Person(char* n, char s, int a); // 생성자
~Person() {}; // 소멸자
private:
char name[40]; // 이름
Person* spause; // 배우자 (binary relationship)
Body* body; // 몸통에 대한 포인터 (Aggregation)
Hand* l_hand; // 왼손에 대한 포인터
Hand* r_hand; // 오른손에 대한 포인터
};
멤버
|
관계 유형
|
설명
|
Person* spause
|
연관관계 (Association)
|
서로 연결된 두 사람 간의 관계 (예: 결혼)
|
Body* body
|
집합관계 (Aggregation)
|
Person이 Body를 포함하지만, Body는 독립적으로 존재 가능
|
Hand* l_hand / r_hand
|
집합관계
|
손 객체는 별도로 존재하며 Person에 "소속"됨
|
복합 연관
class Person {
public:
Person(char* n, char s, int a);
~Person() {};
private:
char name[40];
Person* spause; // 연관관계 (binary relationship)
Body body; // 합성관계 (객체 포함)
Hand l_hand; // 합성관계 (왼손 객체 직접 포함)
Hand r_hand; // 합성관계 (오른손 객체 직접 포함)
};
멤버
|
관계
|
설명
|
Person* spause
|
연관관계 (association)
|
포인터로 다른 사람 참조 (독립 존재 가능)
|
Body body
|
합성관계 (composition)
|
Person에 포함된 객체, 생명주기 공유
|
Hand l_hand, r_hand
|
합성관계
|
객체 내부에 직접 포함됨, Person이 소멸되면 같이 소멸됨
|
연관의 표현

cClass
- 중심 클래스. 아래의 세 가지 관계를 모두 가짐:
- cPart와 합성 관계 (composition)
- cAssoc과 연관 관계 (association)
- cExtended로부터 상속됨 (inheritance)
class cClass {
private:
int _c;
cPart _Part; // 합성관계 (객체 포함)
cAssoc* _Assoc_PTR; // 연관관계 (포인터로 참조)
public:
set1(int n) { _c = n; }
set2(int n) { _Part.set(n); } // 포함된 객체 사용
set3(int n) { _Assoc_PTR->_a = n; } // 연관된 객체 사용
};
class cPart {
private:
int _p;
public:
set(int n) { _p = n; }
};
class cAssoc {
private:
int _a;
public:
set(int n) { _a = n; }
};
class cExtended : public cClass {
private:
int _e;
public:
set(int n) { _e = n; }
};
파생클래스

const int Max = 20;
class Manager : public Employee {
public:
Manager(char* n, char s, int a, int n = 0) : Employee(n, s, a, n) {
for (int i = 0; i < Max; i++) group[i] = 0;
}
Employee* getEmployee(int n) { return group[n]; }
void setEmployee(Employee* e, int a) { group[a] = e; }
~Manager() { delete[] group; }
private:
Employee* group[Max]; // Manager : Employee 1대 다 관계
};
- Manager는 Employee를 상속받은 파생 클래스
- Manager는 Employee* group[Max] 배열을 통해 여러 명의 Employee 객체를 관리
- 즉, Manager → 다수 Employee : 1:N 연관 관계
- 생성자에서는 group 배열을 초기화하고, 소멸자에서 delete[] group 호출
main() {
Employee ed("Edward", 'm', 21, 20000);
ed.setSalary(25000); // 급여 인상
Manager jane("Jane", 'f', 25);
jane.setSalary(100000); // 매니저는 높은 급여
jane.setEmployee(&ed, 0); // Edward를 0번 인덱스로 그룹에 등록
ed.setSalary(15000); // Edward 급여를 다시 낮춤
}
- Employee 객체 ed와 Manager 객체 jane을 각각 생성
- jane은 자신의 group[0]에 ed를 저장함 (포인터 연결)
- jane은 ed의 직접 소유자가 아닌 연결된 관계
- 이후 ed의 급여는 개별적으로 다시 수정됨 → 독립 객체
추상클래스

class Item {
public:
virtual void cut() = 0;
virtual void move(Length dx, Length dy) = 0;
virtual Boolean pick(Length px, Length py) = 0;
virtual void ungroup() = 0;
}; // 인터페이스 virtual 키워드 사용
class Shape : public Item {
public:
void cut() = 0;
void draw() { write(Color_Foreground); }
void erase() { write(Color_Background); }
void move(Length dx, Length dy) { x += dx; y += dy; }
virtual Boolean pick(Length px, Length py) = 0;
void ungroup() = 0;
virtual void write(Color color) = 0;
protected:
Length x, y;
};
class Box : public Shape {
public:
Box(Length x0, Length y0, Length w, Length h) : Shape() { ... }
Boolean pick(Length px, Length py) { ... }
void move(Length dx, Length dy) { ... }
protected:
Length width, height;
};
class Circle : public Shape {
public:
Circle(Length x0, Length y0, Length radius) : Shape() { ... }
Boolean pick(Length px, Length py) { ... }
void move(Length dx, Length dy) { ... }
void write(Color color) { ... }
protected:
Length radius;
};
Box, Circle는 Shape의 추상 메서드를 구현하는 구체 클래스
Circle은 write()까지 구현하여 완전히 인스턴스화 가능
Box는 write()가 없음 → 여전히 추상 클래스일 가능성 있음
- Item: 공통 인터페이스 제공
- Shape: 위치(x, y) 등 공통 속성과 일부 기능을 구현한 중간 추상 클래스
- Box, Circle: 도형별 구현을 제공하여 실제 사용할 수 있는 클래스
추상 클래스 c ++ 에선 virtual로 , Java에선 abstract로 표현한다
이진 연관
class Person {
public:
Person(char* n, char s, int a); // 생성자
Person* getSpouse() { return spouse; }
void setSpouse(Person* p); // 배우자 설정 함수
~Person() {}
private:
char name[40];
char sex;
int age;
Person* spouse; // 배우자 관계를 가리키는 포인터
};
//spouse: 해당 객체가 연결된 다른 Person 객체를 가리킴
//양방향 이진 연관 관계를 구현하고자 함 (A ↔ B 형태)
void Person::setSpouse(Person* p)
{
if (spouse != p) { // 이미 같은 사람이면 무시
if (spouse == 0) { // 현재 배우자가 없다면
spouse = p; // 새 배우자 설정
p->setSpouse(this); // 상대도 나를 배우자로 설정 (결혼)
return;
}
// 현재 배우자가 나와 연결 안 되어 있으면 이혼 처리
if (spouse->getSpouse() != this) {
Person* old = spouse; // 기존 배우자 임시 저장
spouse = 0; // 나의 배우자 끊기
old->setSpouse(0); // 상대의 배우자도 끊기
}
spouse = p; // 새 배우자 설정
if (spouse != 0) {
spouse->setSpouse(this); // 상대도 나를 배우자로 설정
}
}
}
상황
|
처리
|
spouse == p
|
이미 배우자일 경우 아무것도 하지 않음
|
현재 배우자가 없음 (spouse == 0)
|
p를 배우자로 설정하고, p도 나를 배우자로 설정함 (결혼)
|
현재 배우자가 있고, spouse->getSpouse() != this
|
한쪽만 배우자 설정한 상태 → 서로 이혼 처리
|
새로운 배우자 설정 후
|
spouse->setSpouse(this) 호출로 상대방도 양방향 연관 유지
|
다대일 연관
class Person {
public:
Person(char* n, char s, int a);
Person* getFather() { return father; }
Person* getMother() { return mother; }
Person* getChildren(); // (정의는 생략됨)
void addChild(Person* p) {
children.insert(p);
}
void setFather(Person* p) {
father = p;
if (p) {
p->addChild(this);
return;
}
}
void setMother(Person* p) {
mother = p;
if (p) {
p->addChild(this);
return;
}
}
~Person() {}
private:
char name[40];
char sex;
int age;
Person* father;
Person* mother;
Set children; // 자녀 목록 저장 (insert 메서드 사용 가능)
};
관계
|
구현 방식
|
자식 → 부모
|
father, mother 포인터 (다대일)
|
부모 → 자식
|
children 집합(Set) (일대다)
|
동기화
|
부모를 설정하면 addChild(this)로 자동 연결
|
- setFather(p) 또는 setMother(p) 호출 시:
- this 객체의 부모 포인터 설정 (father = p)
- 부모 객체의 자식 목록에 this를 추가 (p->addChild(this))
- addChild(p):
- children 집합에 해당 자식 p를 추가함
다대다 연관

- 하나의 Person은 여러 Company에 소속될 수 있고
- 하나의 Company도 여러 Person을 고용할 수 있음
- 독립적인 연관 객체(Association Object) 사용
- 중간에 있는 사각형은 연관 테이블 또는 클래스 (예: Employment)
- 각각의 row는 Person과 Company 사이의 하나의 관계를 나타냄
- 포인터 또는 참조를 양쪽 모두 보유
- Employment 객체는 Person과 Company 모두를 참조함
- 이 방식은 관계 자체에 속성(예: 입사일, 직급)을 추가할 수 있는 유연함 제공
728x90
'💾 lecture > 소프트웨어분석 및 설계' 카테고리의 다른 글
[소프트웨어분석 및 설계] UP Modeling 기법 (3) | 2025.06.29 |
---|---|
[소프트웨어분석 및 설계] 시퀀스 다이어그램 (0) | 2025.06.29 |
[객체 지향 설계와 분석을 위한 UML 기초와 응용] 8장 상태 다이어그램 (0) | 2025.04.15 |
[객체 지향 설계와 분석을 위한 UML 기초와 응용] 4장 연습문제 (0) | 2025.04.12 |
[객체 지향 설계와 분석을 위한 UML 기초와 응용] 3장 연습문제 (0) | 2025.04.12 |