본문 바로가기

Develop/Design Pattern

[Design Pattern] 경량 (Flyweight) 패턴

728x90

1. 개요

  • 경량 디자인 패턴 (Flyweight Design Pattern)내부 상태(Intrinsic)와 외부 상태(Extrinsic)를 구분하는 패턴이다.

1.1. 설명

  • 내부 상태(Intrinsic): 객체가 독립적으로 가지고 있는 고유한 상태 - Flyweight
  • 외부 상태(Extrinsic): 여러 객체가 공유하는 상태

2. 상황

  • 많은 수의 유사한 객체를 생성해야 할 때
  • 내부 상태와 외부 상태를 명확히 구분해야 할 때

3. 다이어그램

flyweight-default

3.1. 설명

    • Flyweight
      • ConcreteFlyweight 의 인터페이스

 

    • ConcreteFlyweight
      • 공유될 객체의 내부 상태를 저장하고, 외부 상태를 공유한다.
      • operation(String context) 메소드를 구현하여 외부 상태에 따른 동작을 수행한다.

 

  • FlyweightFactory
    • Flyweight 객체를 생성 및 관리한다.
    • Flyweight 의 재생성을 방지한다.
    • getFlyweight(String key) 메소드를 통해 요청된 공유 객체를 반환한다.

4. 구현

interface Flyweight {
  void operation(String extrinsic);
}

public class ConcreteFlyweight implements Flyweight {
  private String intrinsic;

  public ConcreteFlyweight(String intrinsic) {
    this.intrinsic = intrinsic;
  }

  @Override
  public void operation(String extrinsic) {
      System.out.println("Intrinsic: " + intrinsic + ", Extrinsic: " + extrinsic);
  }
}

public class FlyweightFactory {
  private Map<String, Flyweight> flyweights;

  public FlyweightFactory() {
    flyweights = new HashMap<>();
  }

  public Flyweight getFlyweight(String key) {
    Flyweight flyweight = flyweights.get(key);

    if (flyweight == null) {
      flyweight = new ConcreteFlyweight(key);
      flyweights.put(key, flyweight);
    }

    return flyweight;
  }
}
public class Client {
  public static void main(String[] args) {
    FlyweightFactory factory = new FlyweightFactory();

    Flyweight flyweight1 = factory.getFlyweight("Intrinsic1");
    flyweight1.operation("Extrinsic1");

    Flyweight flyweight2 = factory.getFlyweight("Intrinsic2");
    flyweight2.operation("Extrinsic2");

    Flyweight flyweight3 = factory.getFlyweight("Intrinsic1");
    flyweight3.operation("Extrinsic3");
  }
}

5. 예시

public interface Flyweight { void draw(int x, int y); }

class Sprite implements Flyweight {
  private String name;
  private String imagePath;

  public Sprite(String name, String imagePath) {
    this.name = name;
    this.imagePath = imagePath;
  }

  public void draw(int x, int y) {
    System.out.println("Drawing sprite (" + x + ", " + y + "): " + name);
  }
}

public class SpriteFactory {
  private static Map<String, Flyweight> sprites = new HashMap<>();

  public static Flyweight getSprite(String name, String imagePath) {
    Flyweight sprite = sprites.get(name);

    if (sprite == null) {
      System.out.println(name + " object constructed");
      sprite = new Sprite(name, imagePath);
      sprites.put(name, sprite);
    }

    return sprite;
  }
}
public class Client {
  public static void main(String[] args) {
    Flyweight sprite1 = SpriteFactory.getSprite("Sprite1", "image1.png");
    sprite1.draw(10, 20);

    Flyweight sprite2 = SpriteFactory.getSprite("Sprite2", "image2.png");
    sprite2.draw(30, 40);

    Flyweight sprite3 = SpriteFactory.getSprite("Sprite1", "image1.png");
    sprite3.draw(50, 60);
  }
}

실행결과

Sprite1 object constructed
Drawing sprite (10, 20): Sprite1
Sprite2 object constructed
Drawing sprite (30, 40): Sprite2
Drawing sprite (50, 60): Sprite1

6. 장단점

6.1. 장점

  • 객체 간의 상태 공유가 가능하다.
  • 게임 개발 등 많은 수의 객체를 사용하는 서비스에 유용하다.
  • 메모리 사용을 최적화할 수 있다.

6.2. 단점

  • 코드의 복잡성이 증가한다.

관련 포스팅

728x90