플라이웨이트 패턴(Flyweight Pattern)
총과 파편이 난무하는 게임을 만들었다 가정해보자. 곧이어 게임이 죽었다. 이유는 총알, 미사일 등과 같은 입자가 데이터를 가지는 별도의 객체로 표시되었고, 이를 플레이어의 컴퓨터가 RAM이 감당하지못해서 프로그램이 충돌한 것이다.
해결
총알이나 파편등의 입자 클래스는 색상과 스프라이트를 가진다 이것은 변하지 않고 입자마다 일정하게 유지된다. 반면 속도나 좌표값은 각 입자마다 고유하며 시간에 따라 값이 변하게 된다.
색상과 스프라이트 같은 상수데이터를 고유한 상태라고 한다. 다른 객체들에 의해 외부에서 변경되는 객체의 나머지 상태를 공유한 상태라고 한다.
플라이웨이트 패턴은 객체 내부에 공유한 상태의 저장을 중단하고, 이 상태를 의존하는 특정 메서드들에게 전달한다. 고유한 상태만 객체 내에 유지되므로 해당 고유한 상태는 콘텍스트가 다른 곳에서 재사용할 수 있다.
고유한 상태만 객체 내에 유지되므로 해당 고유한 상태는 콘텍스트가 다른 곳에서 재상요할 수가 있다. 이러한 객체들은 공유한 상태보다 변형이 훨씬 적은 고유한 상태에서만 달라지므로 훨씬 더 적은 수의 객체만 있으면 된다.
총알, 미사일, 파편의 세 가지 다른 객체만으로도 게임의 모든 입자를 나타낼 수 있는 것을 볼 수 있다. 고유한 상태만 저장하는 객체를 플라이웨이트라고 한다
공유한 상태 스토리지
대부분의 공유한 상태는 패턴을 적용하기 전에 객체들을 집합시키는 컨테이너 객체로 이동된다.
파티클 필드에 모든 입자를 저장하는 주요 Game객체이다. 공유한 상태를 이 클래스로 이동하려면 개별 입자의 좌표, 벡터 및 속도를 저장하기 위한 여러 배열 필드들을 생성해야한다. 입자를 나타내는 특정 플라이웨이트에 대한 참조를 저장하려면 다른 배열이 필요하다. 이러한 배열들은 같은 인덱스를 사용하여 입자의 모든 데이터에 액세스할 수 있도록 동기화 되어야한다.
이보다 더 좋은 해결책은 플라이웨이트 객체에 대한 참조와 함께 공유된 상태를 저장할 별도의 콘텍스트 클래스를 만드는 것이다. 이 접근 방식을 사용하려면 컨테이너 클래스에 단일 배열만 있으면 된다. 이렇게 되면 콘텍스트가 많아지지만 입자 객체만큼 많이 생기지는 않는다.
플라이웨이트와 불변성
같은 플라이 웨이트 객체가 다른 콘텍스트들에서 사용될 수 있으므로 해당 플라이웨이트 객체의 상태를 수정할 수 없는지 확인해야한다. 플라이웨이트 생성자 매개변수들을 통해 상태를 한 번만 초기화해야한다. setter또는 public 필드들을 다른 객체들에 노출해서는 안 된다.
구조
장단점
프로그램에 유사한 객체들이 많다고 가정하면 많은 RAM을 절약할 수 있다
누군가 플라이웨이트 메서드를 호출할 때마다 콘텍스트 데이터의 일부를 다시 계산해야 한다면 cpu주기 대신 ram을 절약하고 있는 것일지도 모른다
코드가 복잡해지므로 새 팀원은 왜 개체의 상태가 그런 식으로 분리되었는지 궁금해야할 것이다.