해당 글은 Tstory 블로그 Dev inpa에 출처를 두고 있습니다.
이번 패턴은 Flyweight 패턴에 관한 글이다.
나는 살면서 처음 들어보는 생소한 패턴이다.
Flyweight?
패턴의 이름을 말 그대로 직역하면 경량 패턴이다.
정의도 이름을 따라가는데, 아래와 같이 간단하게 정의할 수 있겠다.
객체의 생성을 줄여 메모리를 경량화하기 위한 패턴!
말 그대로 객체를 경량화 시킬 수 있는 패턴이다.
아래로 예시를 보며 좀 더 자세하게 공부해보도록 하자.
사용 이유
예를 들어 마인크래프트 게임을 한 번 생각해보자.
게임 내에서 어떤 필드가 주어지고, 해당 필드에 나무가 생성이 된다.
이 때 나무들은 각자 특징을 가질 수 있으며, 모두 하나의 객체로 취급된다.
아래와 같이 나무 객체, 지형 객체, 그리고 전체 메모리가 있다고 가정하자.
각각의 객체를 자바 코드로 구현한 것이다.
이 코드들 기반으로 각 특징 별 나무를 5그루씩 심어보도록 하겠다.
아래와 같이 메인 함수에서 나무를 심는 시뮬레이션이 가능하다.
미리 생성된 10000
크기의 지형에 나무를 5그루씩 심었다.
나무를 심을 때 마다 객체가 생성되므로, 총 15그루의 나무를 심었다.
따라서 총 사용된 메모리는 100 * 15 = 1500MB
가 된다.
사실 생각해보면, 나무들의 특성인 mesh, texture
은 어떤가?
같은 특징의 나무라면 분명히 동일한 mesh, texture
를 가지게 된다.
즉, 같은 특징의 나무는 위치만 다르지 동일한 특성을 갖는다는 것이다!
그럼 사실상 우리는 메모리를 낭비하고 있다고 볼 수 있다.
이럴 때 사용할 수 있는 패턴이 바로 Flyweight 패턴!
구현
객체들 간에 중복되는 특징인 mesh, texture
을 하나의 클래스로 빼낸다.
이 클래스를 우리는 Flyweight
클래스라고 칭하겠다.
또한, 공통된 부분은 변경될 일이 없으므로 final
로 선언한다.
공통된 부분을 빼내었으면 이제 해당 클래스를 생산할 공장이 필요하다.
그냥 해당 객체를 생성하는 것이 아닌 유일한 객체를 생성하기 위함이다.
정적 팩토리 메서드
를 이용해서 유일한 객체를 반환할 수 있다.
위와 같이 정적 팩토리 메서드
를 통해 객체를 생산함을 볼 수 있다.
메서드의 형태가 Singleton
과 굉장히 유사함을 확인할수 있다.
사실 Singleton
또한 정적 팩토리 메서드
가 사용된다.
이제 위와 같이 구현했다면, Tree
객체를 직접 생성하지 않아도 된다.
아래와 같이 Flyweight
객체를 선언하여 객체를 생성하도록 한다.
해당 객체는 Cache
에 저장되며, 이후 동일한 특성의 객체 생성이 요청되면,
기존의 Cache
를 확인하여 해당 특성의 객체를 반환해준다.
그 결과 실제 메인 함수에서 특성 별 나무가 아래와 같이 생성된다.
특성 별로 처음 나무를 생성할 때만 객체가 생생됨을 확인할 수 있다.
또한 메모리의 사용량이 420MB
로 크게 줄었음을 확인할 수 있다.
Flyweight 객체 90MB
에 좌표 객체 10MB
가 5개 생성되어,
(90 + 10 * 5) * 3
의 계산으로 420MB
가 된 것이다.
이렇게 공통 요소가 있어 반복 객체 생성을 할 필요가 없는 경우에,
경량 객체를 선언하여 한 번만 객체를 생성하도록 할 수 있는 패턴이다.
주의할 점
주의할 점은 위의 코드에서 구현했던 Cache
이다.
우리가 직접 HashMap
을 선언해서 인스턴스를 Cache
로서 관리하는 것인데,
JVM
의 GC(Garbage Collection)
은 관리되는 인스턴스는 삭제하지 않는다.
즉, Cache
는 더 이상 사용하지 않아도 GC
가 해제하지 못한다.
따라서 더 이상 참조할 필요가 없는 객체라면, 직접 메모리를 해제해주어야 한다.