[Design Pattern] 플라이웨이트 패턴

FlyWeight Pattern

플라이웨이트 패턴은 공유를 통해 많은 수의 작은 객체들을 효과적으로 지원하는 패턴이다. 즉 플라이웨이트 객체는 공유 가능한 객체로 여러 비슷한 상황에서 플라이웨이트 객체를 사용할 때 저장소의 비용을 줄여줄 수 있다. 플라이웨이트 패턴에서 중요한 개념은 본질적(instrinsic) 상태부가적(extrinsic) 상태의 구분이다. 플라이웨이트 객체는 본질적 상태만을 가져야 하며 부가적 상태는 플라이웨이트 객체가 사용되는 상황에 종속적이게 된다.

활용성

  1. 응용프로그램이 대량의 객체를 사용해야 할 때
  2. 객체의 수가 너무 많아져 저장 비용이 너무 높을 때
  3. 대부분의 객체 상태를 부가적인 것으로 만들 수 있을 때
  4. 객체들의 부가적인 속성들을 제거한 후 많은 묶음이 비교적 적은 수의 공유된 객체로 대체될 수 있을 때
  5. 응용프로그램이 객체의 식별성에 의존하지 않을 때

플라이웨이트 패턴 사용에 따른 결과

저장소 절약

플라이웨이트 패턴은 과거 본질적인 상태에 저장되던 객체를 부가적인 상태와 본질적 상태로 분리하여 부가적 상태의 연산 비용을 런타임에 추가시킨다. 하지만 이런 비용은 플라이웨이트 객체의 공유를 통한 저장소 절약이라는 반대 급부를 가진다. 저장소 절약의 장점은 다음과 같다.

  • 공유해야 하는 인스턴스의 전체 수 감소
  • 객체별 본질적 상태의 양 감소
  • 부가적인 상태는 연산되거나 저장될 수 있음

플라이웨이트

구조

플라이웨이트의 구조는 다음과 같다.

FlyWeight Pattern Diagram

C++ 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void FlyWeightPattern::FlyWeightPattern()
{
addFlyWeight();
getFlyWeight();
}

void FlyWeightPattern::addFlyWeight()
{
CharacterFactory* characterFactory = CharacterFactory::getInstance();
characterFactory->getCharacter('a');
characterFactory->getCharacter('b');
characterFactory->getCharacter('c');
characterFactory->getCharacter('a');
characterFactory->getCharacter('d');
}

void FlyWeightPattern::getFlyWeight()
{
CharacterFactory* characterFactory = CharacterFactory::getInstance();
Character* a = characterFactory->getCharacter('a');
Character* b = characterFactory->getCharacter('b');
Character* c = characterFactory->getCharacter('c');
Character* aPrime = characterFactory->getCharacter('a');
Character* d = characterFactory->getCharacter('d');

std::cout<<a<<"\t"<<a->getChar()<<std::endl;
std::cout<<aPrime<<"\t"<<aPrime->getChar()<<std::endl;
std::cout<<b<<"\t"<<b->getChar()<<std::endl;
std::cout<<c<<"\t"<<c->getChar()<<std::endl;
std::cout<<d<<"\t"<<d->getChar()<<std::endl;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class CharacterFactory
{
std::vector<Character*> charList;
static CharacterFactory* instance;
CharacterFactory() {};
public:
static CharacterFactory* getInstance()
{
return instance;
}

Character* getCharacter(char c)
{
for(Character* character : charList)
if(character->getChar() == c)
return character;

Character* character = new Character(c);
charList.emplace_back(character);
return character;
}
};

CharacterFactory* CharacterFactory::instance = new CharacterFactory();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Character
{
char c;
public:
Character(char c)
{
this->c = c;
}

char getChar()
{
return this->c;
}
};

java 구현

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Client {
public static void main(String[] args) {
addCharacter();
getCharacter();
}

public static void addCharacter() {
CharacterFactory.INSTANCE.getCharacter('a');
CharacterFactory.INSTANCE.getCharacter('b');
CharacterFactory.INSTANCE.getCharacter('c');
CharacterFactory.INSTANCE.getCharacter('a');
CharacterFactory.INSTANCE.getCharacter('d');
}

public static void getCharacter() {
Character a = CharacterFactory.INSTANCE.getCharacter('a');
Character aPrime = CharacterFactory.INSTANCE.getCharacter('a');
Character b = CharacterFactory.INSTANCE.getCharacter('b');
Character c = CharacterFactory.INSTANCE.getCharacter('c');
Character d = CharacterFactory.INSTANCE.getCharacter('d');

System.out.println(System.identityHashCode(a) + " " + a.getC());
System.out.println(System.identityHashCode(aPrime) + " " + aPrime.getC());
System.out.println(System.identityHashCode(b) + " " + b.getC());
System.out.println(System.identityHashCode(c) + " " + c.getC());
System.out.println(System.identityHashCode(d) + " " + d.getC());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public enum CharacterFactory {
INSTANCE;

private List<Character> list;

private CharacterFactory() {
list = new ArrayList<>();
}

Character getCharacter(char c) {
for(Character character : list)
if(character.getC() == c)
return character;

Character character = new Character(c);
list.add(character);
return character;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Character {
private char c;

public Character(char c) {
this.c = c;
}

public char getC() {
return c;
}

@Override
public boolean equals(Object obj) {
if(!(obj instanceof Character)) return false;
Character character = (Character)obj;
return character.c == c;
}
}
Author: Song Hayoung
Link: https://songhayoung.github.io/2020/08/20/Design%20Pattern/FlyWeightPattern/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.