소프트웨어에 대한 모든 것

[디자인패턴][Flyweight] 플라이웨이트 패턴 본문

시스템 설계 및 디자인/디자인 패턴

[디자인패턴][Flyweight] 플라이웨이트 패턴

앤테바 2022. 3. 29. 07:51
반응형

Flyweight 패턴, 출처 - https://morioh.com/p/85c87296844b

플라이웨이트 패턴 정의

  • 동일하거나 유사한 객체들 사이에 가능한 많은 데이터를 서로 공유하여 메모리 사용량을 최소화하는 패턴
  • 공유되는 많은 객체의 수를 줄여서 메모리 사용량을 줄여주는 패턴
  • 특정 클래스의 인스턴스 한 개만 가지고 여러 개의 가상 인스턴스를 제공
플라이웨이트 패턴은
객체를 공유하는 방식으로 객체를 구성해서
메모리 사용량을 줄이는 패턴입니다.

플라이웨이트 패턴은 현업에서 개발을 하면 자기도 모르게 쓰고 있을 패턴입니다. 중복적인 객체가 있고 메모리 사용량이 많으면 하나만 생성해서 공유해서 사용하도록 디자인 해소 부지불식간에 플라이웨이트 패턴을 적용 했을 것이지요. 

플라이웨이트 패턴 클래스 다이어그램

플라이웨이트 패턴은 여러 다양한 방법으로 활용되어 구현될 수 있기 때문에 아래의 한 가지 클래스 다이어그램이 정답이라고 할 수 없습니다. 참고 정도로만 사용하면 좋을 것 같습니다. 중요한 것은 중복되는 객체는 공유해서 사용한다는 것입니다.

Flyweight 패턴 Class Diagram

플라이웨이트 패턴 활용

무수한 원을 화면에 그리는 예제를 들겠습니다. 원은 x, y, radius(반경), 백그라운드 이미지 속성을 갖습니다. 수 천, 수 만개의 원을 화면에 그릴 수 있습니다. 백그라운드 이미지는 flower.png, buttery.png 이미지가 될 수 있습니다. 만약 플라이웨이트 패턴을 적용하지 않는 다면 10,000개의 원을 그리기 위해서는 이미지 10,000개를 메모리에 로드해야하는 불상사가 발생합니다. 메모리를 쓸데 없이 많이 소비하는 거죠.  이미지 파일 하나의 사이즈가 1MB이면 10,000개를 메모리에 로드하기 위해서는 10GB 메모리가 필요합니다. PC의 램이 10GB 이하라면 프로그램은 메모리가 부족하여 강제 종료될 것입니다.

플라이웨이트 패턴 적용 전

 

 

플라이웨이트 패턴을 적용해서 백그라운드 이미지는 최대 2개만 로드해서 공유해서 사용토록 합니다. 그러면 단 2MB면 충분합니다.  원 이미지를 아무리 많이 생성해서 이미지는 단 2개만 생성되고 공유가 되는 것입니다. 이게 바로 플라이웨이 패턴의 효과입니다. 중복되는 객체는 더 이상 생성하지 않고 공유해서 사용한다.

플라이웨이트 패턴 적용 후

 

클래스 다이어 그램은 예제 코드는 아래와 같습니다.

import random
from abc import ABC, abstractmethod


class Shape(ABC):
    @abstractmethod
    def draw(self):
        pass


class Circle(Shape):
    def __init__(self, x, y, radius, bg_image):
        self.x = x
        self.y = y
        self.radius = radius
        self.bg_image = bg_image

    def draw(self):
        print(f'draw circle - x : {self.x}, y : {self.y}, '
              f'radius : {self.radius}, bg_image : {self.bg_image.filename}')


class Image:
    def __init__(self, filename):
        self.filename = filename
        print(f'load image from {self.filename}')


class ShapeFactory:
    bg_images = {}

    @classmethod
    def get_circle(cls, x, y, radius, bg_image_filename):
        bg_image = cls.bg_images.get(bg_image_filename, None)
        if bg_image is None:
            bg_image = Image(bg_image_filename)
            cls.bg_images[bg_image_filename] = bg_image

        return Circle(x, y, radius, bg_image)


bg_image_filenames = ['flower.png', 'butterfly.png']

circles = []
for i in range(10):
    x = random.randint(0, 1000)
    y = random.randint(0, 1000)
    radius = random.randint(1, 100)
    bg_image_filename = bg_image_filenames[radius % len(bg_image_filenames)]

    circle = ShapeFactory.get_circle(x, y, radius, bg_image_filename)
    circles.append(circle)

for circle in circles:
    circle.draw()

출력

load image from flower.png
load image from butterfly.png
draw circle - x : 243, y : 276, radius : 30, bg_image : flower.png
draw circle - x : 740, y : 568, radius : 17, bg_image : butterfly.png
draw circle - x : 718, y : 316, radius : 62, bg_image : flower.png
draw circle - x : 723, y : 754, radius : 58, bg_image : flower.png
draw circle - x : 945, y : 831, radius : 6, bg_image : flower.png
draw circle - x : 411, y : 430, radius : 56, bg_image : flower.png
draw circle - x : 973, y : 235, radius : 24, bg_image : flower.png
draw circle - x : 327, y : 477, radius : 62, bg_image : flower.png
draw circle - x : 101, y : 705, radius : 71, bg_image : butterfly.png
draw circle - x : 886, y : 81, radius : 87, bg_image : butterfly.png

 

참고 자료

https://www.tutorialspoint.com/design_pattern/flyweight_pattern.htm

https://refactoring.guru/design-patterns/flyweight

반응형
Comments