본문 바로가기
SW

GoF의 디자인 패턴(Design Patterns: Elements of Reusable Object-Oriented Software) - 4장 구조 패턴 :: 플라이급(Flyweight)

by 라꾸스떼(YR) 2020. 4. 30.
반응형

[플라이급(Flyweight) - 객체 구조]

<의도>

오유를 통해 많은 수의 소립(fine-grained) 객체들을 효과적으로 지원한다.

 

<동기>

문자 하나를 객체로 관리하는 데는 비용이 많이 든다. 얼마되지 않는 분량의 문서라 하더라도 수천 개의 문자 객체를 포함할 것이고, 이는 엄청난 메모리와 예상치 못한 실행 시간 낭비를 가져올 수 있다. 플라이급 패턴은 이런 문제를 객체 공유를 통해 해결하는 방법을 보여준다.

플라이급 객체는 공유 가능한 객체이며, 각각의 상황에서는 독립적인 객체로 동작한다. 이것은 공유될 수 없는 객체의 인스턴스와 구분이 안 된다는 의미이다. 플라이급 패턴에서 중요한 개념은 본질적(instrinsic) 상태와 부가적(extrinsic) 상태의 구분이다. 본질적 상태는 플라이급 객체에 저장되어야 하며, 이것이 적용되는 상황과 상관없는 본질적 특성 정보들이 객체를 구성한다. 본질적이지 않은 부가적 상태는 플라이급 객체가 사용될 상황에 따라 달라질 수 있고, 그 상황에 종속적이다. 그러므로 공유될 수 없다. 사용자 객체는 이런 부가적 상태를 그것이 필요한 플라이급 객체에 전달해야 하는 책임을 갖는다.

각각의 글자를 인스턴스로 갖기보다는 문서에 각 글자들이 나타날 때마다 플라이급 객체의 공유된 풀에 존재하는 인스턴스에 대한 참조자를 갖도록 관리한다.

'a' 글자를 표현하는 플라이급 객체는 해당 글자 코드를 저장하지만, 위치나 폰트는 저장하지 않는다. 사용자는 이 상황에 따른 정보를 전달해 준다.

 

<활용성>

-응용프로그램이 대량의 객체를 사용해야 할 때

-객체의 수가 너무 많아져 저장 비용이 너무 높아질 때

-대부분의 객체 상태를 부가적인 것으로 만들 수 있을 때

-부가적인 속성들을 제거한 후 비교적 적은 수의 공유된 객체로 대체될 수 있을 때(단, 본질이 다른 객체가 아님)

-응용프로그램이 객체의 정체성에 의존하지 않을 때

 

<구조>

-

 

<참여자>

-Flyweight : Flyweight가 받아들일 수 있고, 부가적 상태에서 동작해야 하는 인터페이스를 선언한다.

-ConcreteFlyweight : Flyweight 인터페이스를 구현하고 내부적으로 갖고 있어야 하는 본질적 상태에 대한 저장소를 정의한다. ConcreteFlyweight 객체는 공유할 수 있는 것이어야 한다.

-UnsharedConcreteFlyweight : Flyweight 인터페이스는 공유를 가능하게 하지만, 그것을 강요해서는 안 된다. UnsharedConcreteFlyweight 객체가 ConcreteFlyweight 객체를 자신의 자식으로 갖는 것은 흔한 일이다.

-FlyweightFactory : 플라이급 객체를 생성하고 관리하며, 플라이급 객체가 제대로 공유되도록 보장한다.

-Client : 플라이급 객체에 대한 참조라를 관리하며 플라이급 객체의 부가적 상태를 저장한다.

 

<협력 방법>

-플라이급 객체가 기능을 수행하는 데 필요한 상태가 본질적인 것인지 부가적인 것인지를 구분해야 한다. 본질적 상태는 ConcreteFlyweight에 저장해야 하고, 부가적인 상태는 사용자가 저장하거나, 연산되어야 하는 다른 상태로 관리해야 한다. 사용자는 연산을 호출할 때 자신에게만 필요한 부가적 상태를 플라이급 객체에 매개변수로 전달한다.

-사용자는 ConcreteFlyweight의 인스턴스를 직접 만들 수 없다. 사용자는 ConcreteFlyweight 객체를 FlyweightFactory 객체에서 얻어야 한다.

 

<결과>

플라이급 패턴은 예전에는 모두 본질적인 상태로 저장되어 있던 것을 부가적인 상태로 만들어, 부가적인 상태의 연산과 전송에 드는 런타임 비용이 있다. 하지만 플라이급 객체의 공유를 통해 저장소 절약을 가질 수 있다.

-공유해야 하는 인스턴스의 전체 수를 줄일 수 있다.

-객체별 본질적 상태의 양을 줄일 수 있다.

-부가적인 상태는 연산되거나 저장될 수 있다.

플라이급 패턴은 복합체 패턴과 조합하여 그래프와 같이 계층적 구조를 모델링하는 데 사용한다. 이렇게 하면, 플라이급 단말 노드들은 자신의 부모에 대한 포인터를 저장할 수 없기 때문에, 부모 포인터를 부가적 상태의 일부로서 플라이급 객체에다가 매개변수로 전달해야 한다.

 

<구현>

고려할 사항

1.부가적 상태를 제외한다.

2.공유할 객체를 관리한다. FlyweightFactory 객체는 연관 저장소를 써서 사용자가 자신이 관심 있는 Flywieght를 찾아볼 수 있게 해준다. 공유 가능성은 플라이급 객체가 필요하지 않을 때 그것을 해체하는 참조 카운팅 혹은 가비지 컬렉션 능력에 따라 좌우된다.

 

<예제 코드>

-

 

<잘 알려진 사용예>

-

 

<관련 패턴>

플라이급은 복합체 패턴과 함께 사용되는데, 공유되는 단말 노드를 갖는 방향성 비순환 그래프 형태를 써서 논리적으로 계층 구조를 구현한다.

상태 패턴 또는 전략 패턴을 플라이급 객체로 구현할 수 있다.

반응형

댓글