반응형
1. 플라이웨이트 패턴의 개념
플라이웨이트(Flyweight) 패턴은 여러 개의 유사한 객체를 공유하여 메모리 사용을 최소화하는 구조적 디자인 패턴입니다. 객체를 가능한 한 재사용하고 동일한 데이터를 가진 객체의 생성을 제한함으로써 시스템 리소스를 절약할 수 있습니다.
플라이웨이트 패턴은 자주 사용되는 객체를 캐싱하고, 공유된 상태(공유 데이터)와 비공유 상태(개별 데이터)를 분리하는 방식으로 동작합니다.
2. 플라이웨이트 패턴 클래스 다이어그램
다음은 플라이웨이트 패턴의 클래스 다이어그램입니다:
+-----------------+
| Flyweight |<--------------------+
|-----------------|
|+ operation() |
+-----------------+
/\
|
+----------------+----------------+
| |
+-------------------+ +-------------------+
| ConcreteFlyweight | | UnsharedFlyweight |
|-------------------| |-------------------|
|+ operation() | |+ operation() |
+-------------------+ +-------------------+
+-----------------------+
| FlyweightFactory |
|-----------------------|
|+ getFlyweight(key) |
+-----------------------+
설명:
- Flyweight: 공유 객체들이 구현할 인터페이스입니다.
- ConcreteFlyweight: 공유 상태를 가지는 객체입니다.
- UnsharedFlyweight: 공유되지 않는 객체로, 비공유 상태를 가진 객체입니다.
- FlyweightFactory: 객체 생성을 관리하며, 이미 생성된 객체를 캐싱하여 재사용합니다.
3. 플라이웨이트 패턴의 실제 적용
플라이웨이트 패턴은 다음과 같은 상황에 유용합니다:
- 대량의 유사한 객체를 생성해야 하는 경우.
- 객체의 개수가 많아져 메모리 사용이 급증하는 경우.
- 객체 간의 상태를 공유할 수 있는 경우.
대표적 사용 사례:
- 문서 편집기에서 문자나 글꼴 객체 공유
- 게임에서 동일한 배경 오브젝트(나무, 돌)를 공유
- 캐시 시스템에서 동일한 요청 결과를 재사용
4. 플라이웨이트 패턴 예제 코드
다음은 Java로 구현한 플라이웨이트 패턴 예제입니다.
예제 설명:
- Character 클래스는 공유 객체입니다.
CharacterFactory
는 이미 생성된 객체를 관리하고 재사용합니다.
코드 구현
import java.util.HashMap;
import java.util.Map;
// Flyweight 인터페이스
interface Flyweight {
void operation(String extrinsicState);
}
// ConcreteFlyweight: 공유 상태를 가지는 객체
class ConcreteFlyweight implements Flyweight {
private final String intrinsicState; // 공유되는 상태
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(String extrinsicState) {
System.out.println("Intrinsic State: " + intrinsicState + ", Extrinsic State: " + extrinsicState);
}
}
// FlyweightFactory: Flyweight 객체를 생성 및 관리
class FlyweightFactory {
private final Map<String, Flyweight> flyweightMap = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (!flyweightMap.containsKey(key)) {
System.out.println("Creating new Flyweight for key: " + key);
flyweightMap.put(key, new ConcreteFlyweight(key));
} else {
System.out.println("Reusing existing Flyweight for key: " + key);
}
return flyweightMap.get(key);
}
}
// 클라이언트 코드
public class FlyweightPatternExample {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
Flyweight flyweight1 = factory.getFlyweight("A");
Flyweight flyweight2 = factory.getFlyweight("A");
Flyweight flyweight3 = factory.getFlyweight("B");
flyweight1.operation("First Call");
flyweight2.operation("Second Call");
flyweight3.operation("Third Call");
}
}
실행 결과
Creating new Flyweight for key: A
Reusing existing Flyweight for key: A
Creating new Flyweight for key: B
Intrinsic State: A, Extrinsic State: First Call
Intrinsic State: A, Extrinsic State: Second Call
Intrinsic State: B, Extrinsic State: Third Call
코드 설명
- Flyweight 인터페이스: 공유 객체가 구현해야 하는 메서드(
operation
)를 정의합니다. - ConcreteFlyweight: 공유 상태(
intrinsicState
)를 포함합니다. - FlyweightFactory: 이미 생성된 객체를 캐싱하여 재사용하거나 새로 생성합니다.
- 클라이언트:
Flyweight
객체를 요청하고operation
을 호출합니다.
5. 플라이웨이트 패턴 사용 시 주의사항
- 상태 구분: 공유 상태와 비공유 상태를 명확하게 구분해야 합니다.
- 오버헤드: 객체를 관리하는 팩토리의 캐싱 로직이 복잡해질 수 있습니다.
- 객체 생성 비용: 초기 객체 생성 시 비용이 발생하지만 재사용을 통해 장기적으로 최적화됩니다.
결론
플라이웨이트 패턴은 메모리 효율성을 극대화하고 동일한 객체를 재사용하는 강력한 패턴입니다. 대량의 객체를 생성하고 관리해야 하는 상황에서 매우 유용하며, 실제 적용 사례도 다양합니다.
위의 예제를 통해 플라이웨이트 패턴의 개념과 사용법을 이해하고 프로젝트에 적절하게 활용해보세요!
반응형
'JAVA > JAVA Design Pattern' 카테고리의 다른 글
JAVA 옵저버(Observer) 패턴 (0) | 2025.01.01 |
---|---|
JAVA 전략(Strategy) 패턴 (0) | 2024.12.30 |
JAVA 브리지(Bridge) 패턴 (0) | 2024.12.28 |
JAVA 퍼사드(Facade) 패턴, 복잡한 시스템을 단순화하는 방법 (0) | 2024.12.27 |
JAVA 접근 제어를 위한 프록시(Proxy) 패턴 (0) | 2024.12.26 |