Immutable Pattern
JLab 편집실 blueduck (최성원)
한객체에 동시접속 오버헤드를 줄이고 레퍼런스를 같은 객체와 공유하여 객체의 견고함(robustness)을 증가시켜 주는 패턴입니다. 객체가 생성된 후에 객체 상태 정보가 빠귀는것을 허락하지 않으므로써 객체의 견고함(robustness)을 이룰수 있습니다. 또한, Immutable 패턴은 한 객체를 공유하는 멀티 쓰레드의 실행을 동기화하는 요구를 피합니다. 내용 여러 객체들에 의해서 사용되어지는 객체의 상태 정보 변경을 동기화하고, 상태정보가 전파되는 것을 막기 위해서 공유되는 객체를 immutable객체로 만들 수 있습니다. immutable객체는 객체가 생긴 후에는 어떠한 상태변화도 허락하지 않습니다. 이는 상태정보를 변경하는 메소드를 포함하지 않음으로써 구현할 수 있습니다. 멤벼 변수 값을 수정하는 set 메소드가 없어야 하는 것이겠지요.
immutable 클래스는 상태변화를 필요로 하지 않으며 여러 다른 객체들에 의해서 사용되어지는 클래스의 경우에 유용하며, 멀티쓰레드에 의해서 공유되는 객체의 상태를 일관성있게 유지해야하는 경유에 유용합니다. 멀티쓰레드에 의해서 공유되는 경우에는 멀티쓰레드의 실행을 동기화할 필요가 없으므로 동기화에 따르는 오버헤드를 줄일수 있으며, 객체의 robustness(견고함,강건함)를 증가시킬 수 있습니다.
immutable클래스를 구현하기 위한 요구사항으로는
* 생성자들을 제외하고 클래스의 멤버 변수 값을 수정하는 메소드(setter 메소드 등)가 없어야 합니다.
* 새로운 상태 정보를 생성하는 메소드는 새로운 인스턴스에 저장해서 그 인스턴스를 반환하도록 해야합니다.
일반적으로 immutable패턴을 read only object라고도 합니다. 예를 들면, 어떤 클래스(Foo)는 getter 메소드와 setter메소드를 모두 가집니다. 그리고 여러 일반 사용자에게 foo객체에 상태 정보를 변경하지 못하도록 제한하기 위해서 ReadOnlyIF를 만들 수 있습니다. ReadOnlyFooIF 인터페이스는 Foo클래스와 동일한 getter메소드들만 가집니다. 그래서 일반 사용자가 ReadOnlyIF를 통해서 간접적으로 Foo객체에 접근하게 함으로써 immutable 패턴의 robustness를 얻을 수 있게 되는 것입니다.
* 모든 인스턴스 변수는 불변해야합니다. 즉, 상수 혹은 "blank" 상수이어야 합니다. 그래야지만, 결국 공개(public)될수 있습니다.
* setter 즉 set 메소드가 없어야 하고 getter 즉 get 메소드만 있어야 합니다.
* 메소드에 의해 상태정보가 바뀐다면 새로운 인스턴스에 저장해서 그 인스턴스를 반환하도록 해야합니다.
* 이러한 이유들 때문에, Immutable 패턴은 멀티쓰레드의 사용을 유용하게 합니다. JAVA API USAGE Java API의 String클래스는 immutable 클래스의 대표적인 예입니다. String 클래스에서는 자신을 나타내는 연속적인 Character들은 객체가 생성될 때 정해지며 변하지 않습니다. String 클래스의 toLowerCase(), subString() 등의 메소드들은 자신의 상태정보(즉, 연속적인 Character들의 값)를 변경하지 않고 새로운 String 객체를 생성해서 반환합니다.
![](https://t1.daumcdn.net/tistoryfile/fs2/6_12_12_12_blog56573_attach_0_29.gif?original)
* 코드 예제
또 하나의 예로 2차원 공간의 위치를 나타내는 Position객체를 생각해 보겠습니다. Position에는 좌표의 위치를 나타내는 x와 y가 멤버변수로 존재합니다. 그리고 x와 y의 offset으로 새로운 Position객체를 생성하는 메소드를 가집니다. 이 메소드는 자신의 x값, y값을 변경하지 않고, 새로운 객체를 생성해서 반환하도록 합니다. Position클래스의 소스코드는 다음과 같습니다.
public class Position {
private int x;
private int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX(){
return this.x;
}
public int getY() {
return this.y;
}
public Position offset(int xoffset, int yoffset) {
return new Position(x + xoffset, y + yoffset);
}
}
관련된 패턴 Single Threaded Execution(Concurrency Pattern)