본문 바로가기
Concepts/UML

UML - 클래스 다이어그램 고급 - 참조 객체, 값 객체

by ocwokocw 2021. 2. 10.

- 이 글은 UML Distilled (마틴 파울러)책을 기반으로 작성하였습니다.

- 참조 객체와 값 객체

보통 객체는 고유성을 가지고 있다. 이는 참조 객체에 대한 이야기이며, 값 객체에서는 해당사항이 없는 이야기이다. 참조 객체는 무엇이고 값 객체는 무엇인가?


- 참조 객체(Reference Object)

참조 객체는 고객과 같은 객체이다. 만약 프로그램에서 고객을 참조한다면, 해당 고객의 참조는 유일하길 원할 것이다. 그래야만 해당 고객에 대한 정보가 변경될 때, 해당 고객을 사용(참조)하고 있던 여러 사용자들(여기서는 사람을 말하는것이 아니라 참조를 하는 다른 코드를 말한다.)에게 해당 정보가 반영될것이다.

 

만약 어떤 고객에 대한 참조가 여러개 있고 이런 참조들이 같은 고객을 참조하고있는지 확인하고 싶으면 고유성을 비교한다.

 

public class Customer{

	private String name;

	public Customer(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}
}

public static void main(String[] args){
	
	Customer importantCustomer = new Customer("important");
	Customer ordinaryCustomer = new Customer("important");
	
	
	Customer refImportantCustomer = importantCustomer;
	
	if(refImportantCustomer == importantCustomer) {
		System.out.println("refImportantCustomer == importantCustomer.");
	}
	
	if(refImportantCustomer == ordinaryCustomer) {
		System.out.println("refImportantCustomer == ordinaryCustomer.");
	}
	
}

 

외와 같이 이름 속성만 가진 Customer 클래스가 있다. 이때 이름이 "important"인 동명이인의 고객 importantCustomer와 ordinaryCustomer가 있다. importantCustomer 를 참조하는 또 다른 참조 refImportantCustomer 객체 참조를 정의한다. 그리고 테스트를 해보면 refImportantCustomer == importantCustomer. 만 출력된다.

 

public class Customer{

	private String name;

	public Customer(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}
	
	public void modifyName(String newName) {
		this.name = newName;
	}
	
}

public static void main(String[] args){
	
	Customer importantCustomer = new Customer("important");
	Customer ordinaryCustomer = new Customer("important");
	
	Customer refImportantCustomer = importantCustomer;
	System.out.println("refImportant's name: " + refImportantCustomer.getName());
	
	importantCustomer.modifyName("moreImportant");
	System.out.println("refImportantCustomer's name: " + refImportantCustomer.getName());
	System.out.println("importantCustomer name: " + importantCustomer.getName());
}

 

이때 Customer에 이름 변경 메소드 modifyName을 추가한다. importantCustomer 의 이름을 변경하면, refImportantCustomer 도 고유성이 동일한 객체를 참조하고 있기 때문에 변경된 이름을 가지게 된다.


- 값 객체(Value Object)

값 객체란 날짜와 같은 것이다. 예를 들어 1989년 9월 2일 이라는 값 객체가 있다고 해보자. 이 값 객체를 참조하는 아주 수많은 객체들이 잇을 것이다. 위의 참조 객체처럼 한 값이 변경되면 모두 변경되어야 할까?

이런 값 객체들은 불변이어야 한다. 이러한 객체들은 같은지를 비교할 때, 고유성을 비교하는것이 아니라 값이 같은지를 비교해야 한다. 아마도 이미 이 예제를 알고 있을 것이다.

 

public static void main(String[] args){
	
	Integer one = new Integer(1);
	Integer otherOne = new Integer(1);
	
	if(one == otherOne) {
		System.out.println("one == otherOne");
	}
	
	if(one.equals(otherOne)) {
		System.out.println("one.equals(otherOne)");
	}
	
}

 

아주 특수한 경우가 아니라면 보통은 서로 다른 1 Integer 객체라 하더라도 동등성 비교연산시 같음을 기대하게 된다. 하지만 == 처럼 고유성 비교를 하면 어쨌든 다른 객체이기 때문에 실패하며, equals 로 내부에 값을 비교하는 로직으로 오버라이딩한 equals 메소드를 사용해야 우리가 기대하던대로 동작하게 된다.


- UML 에서의 표기

사실 위에서 언급한 두 가지는 UML과는 관계없는 자바 기초서에도 나오는 내용일것이다. 보통은 객체에는 너무나 많은 속성이 있고, 참조 객체와 값 객체를 모두 표시하면 알아보기가 힘들 것이므로 보통 표기하지 않는다. 만약 값 객체여부를 강조해야 하는 상황이 있다면 키워드 <<value>>와 <<struct>>를 사용하여 강조한다.

댓글