클래스 다이어그램

라모스·2023년 6월 25일
0

UML 클래스 다이어그램을 사용하면 클래스 내부의 정적인 내용이나 클래스 사이의 관계를 표기할 수 있다. 클래스 다이어그램으로 클래스의 멤버 변수와 멤버 함수를 보여 줄 수 있으며 해당 클래스가 다른 클래스에서 상속되었는지, 다른 클래스를 참조하는지도 알 수 있다.

다시 말해, 소스코드에 나타나는 클래스 사이의 의존 관계를 모두 표기할 수 있다.

기본 개념

클래스

클래스는 단순한 사각형으로 그린다. 클래스 아이콘을 여러 구획으로 나눌 수도 있는데, 첫째 구획에는 클래스의 이름이, 둘째 구획에는 클래스의 변수, 셋째 구획에는 클래스의 메서드가 들어간다.

  • - : private
  • # : protected
  • + : public

변수나 함수 인자의 타입은 저마다 자기 이름 뒤에 콜론을 찍고 적는다. 함수의 반환값도 비슷하게 함수 뒤에 콜론을 찍고 적는다.

public class Dialer {
    public Vector digits;
    private int nDigits;
    public void digit(int n) { }
    protected boolean recordDigit(int n) {
        //...
    }
}

연관

클래스 사이의 연관은 대개 다른 객체의 참조(reference)를 가지는 인스턴스 변수를 의미한다. 화살촉 근처의 이름은 인스턴스 변수의 이름이다. 그리고 화살촉 근처의 숫자는 이 인스턴스 변수가 참조를 몇 개나 가질지 알려준다.

public class Phone {
    private Button[] itsButtons[15];
}

*는 여러 개를 뜻한다. Java에선 이런 연관을 VectorList 또는 다른 컨테이너 타입으로 구현하는 경우가 자주 있다.

public class PhoneBook {
    private Vector itsPnos;
}

상속

UML에선 화살촉을 그릴 때 매우 주의해야 한다. 상속을 표현하는지 연관을 표현하는지 구분하기 힘들 수도 있다.

흔히 상속 관계를 세로로, 연관 관계를 가로로 그린다. UML에서 화살촉의 방향은 모두 소스코드 의존성의 방향이다. UML에서 상속 화살표는 기반 클래스(base class)를 가리킨다.

public class Employee { }

public class SalariedEmployee extends Employee { }

인터페이스와 실체화 관계는 다음과 같이 점선과 화살표로 표기한다.

public interface ButtonListener { }

public class ButtonListenerAdapter implements ButtonListener { }

세부 사항

클래스 스테레오타입

클래스 스테레오타입은 보통 클래스의 이름 위에 놓인 길러멧 사이에 적는데, 앞서 <<interface>> 표기가 바로 이에 해당한다. Java 프로그래머가 사용할 만한 두 가지 스테레오 타입은 다음과 같다.

  • <<interface>> : 이 스테레오타입이 붙은 클래스의 메서드는 모두 추상 메서드이므로, 어떤 메서드도 구현해서는 안된다. 그리고 interface 클래스는 인스턴스 변수를 가지지 못한다. 오직 정적 변수만 가질 수 있다. Java의 인터페이스에 정확히 대응된다.
  • <<utility>> : 이 클래스의 모든 메서드와 변수들은 정적이다. Grady Booch는 이를 흔히 클래스 유틸리티라고 불렀다.

추상 클래스

UML에서 추상 클래스나 추상 메서드를 표기하는 방법은 두 가지다.

  • 이름을 이탤릭체로 적는다.
  • {abstract} 프로퍼티를 사용한다.
public abstract class Shape {
    private Point itsAnchorPoint;
    public abstract void draw();
}

의존성 (Dependency)

의존성 정의

  • 코드에서 두 모듈간의 연결의 의존성이라고 한다.
  • 객체지향 언어에서 두 클래스 간의 관계를 말하기도 한다.

Dependency (의존 관계)

  • A 클래스가 B 클래스를 일시적으로 참조하는 형태이다.

public class B {
    private int numB;
    
    public int getNumB() {
      return this.numB;
    }
}

public class A {
    private int numA;
    
    // add 메소드가 반환한 이후에는 B 클래스의 b 객체는 제거된다. 
    public int add(B b) {
      return numA + b.getNumB();
    }
}

Association (연관 관계)

  • 클래스의 필드로 다른 클래스의 객체를 가지고 있는 관계

public class B {
    private int numB;
    
    public int getNumB() {
      return this.numB;
    }
}

public class A {
    private int numA;
    private B b;
    
    // add 메소드가 반환한 이후에도 B 클래스의 b 객체는 여전히 남아 있다.
    public int add() {
      return numA + this.b.getNumB();
    }
}

Aggregation (집합 관계)

  • Association의 특수한 형태 ('부분/전체' 관계를 내포)
  • 클래스 A와 클래스 B의 생명주기는 반드시 일치하지 않는다.
  • 구현이 연관과 차이는 없다.
  • 집합 관계는 UML 2.0에서 빠져버렸다.

public class B {
    private int numB;
    
    public int getNumB() {
      return this.numB;
    }
}

public class A {
    private int numA;
    private B b;
    
    public A(B externalB) {
        this.b = externalB;
    }
}

Composition (합성 관계)

  • Association의 특수한 형태
  • Aggregation 보다 강결합
  • 클래스 A와 클래스 B의 생명주기가 일치한다.

public class B {
}

public class A {
    private B b;
    
    public A(B externalB) {
        this.b = new B();
    }
}

UML에서 합성에 대한 정의에는 집합과 공통된 규칙 말고도 많은 항목이 들어 있다.

  • 피보호자의 한 인스턴스를 두 주인이 동시에 소유하지 못한다.
  • 주인은 피보호자의 수명 전체의 책임을 진다. 만약 주인이 소멸되면, 피보호자도 함께 소멸되어야 한다. 주인이 복사되면, 피보호자도 복사되어야 한다.

Java에서 객체 소멸은 GC가 수행하므로 어떤 객체의 수명을 관리할 필요는 거의 없다.

References

profile
Step by step goes a long way.

0개의 댓글