본문 바로가기
디자인패턴

플라이급 패턴 (Flyweight Pattern)

by 이석준석이 2021. 7. 12.

사용 의도

  • 객체의 공유를 통해, 인스턴스의 생성을 최적화합니다.

예시

  • 레이싱 경주에서, 1000대의 자동차를 가지고 경기를합니다.
    • 하지만 자동차의 인스턴스의 크기가 매우 크다.
    • 자동차를 운전하는 운전수의 인스턴스는 크기가 작다.
  • 위의 조건에서 객체의 공유를 통해 인스턴스의 생성을 최적화합니다.

구조

참여자 설명
Flyweight Flyweight 클래스들의 추상클래스 혹은 인터페이스입니다.
ConcreteFlyweight Flyweight 를 상속받거나 구현한, 공유될 수 있는 객체들입니다.
UnsharedConcreteFlyweight Flyweight 를 상속받거나 구현한, 공유하지 않는 객체들입니다.
FlyweightFactory Flyweight 를 생성하는 팩토리입니다.

Client 가 Flyweight 객체를 요청하면, 
- 팩토리에 이미 존재하는 경우 : 즉시 반환
- 팩토리에 존재하지 않는 경우 : 생성 후 반환
Client FlyweightFactory 에 객체를 요청하며, 공유하지 않는 개별적인 데이터를 갖고있습니다.

코드

 

RaceCar (Flyweight)

  • 자동차에 두종류가 있으며, 아래와 같다고 할 때, 이름 / 속력 / 마력은 하나의 공유하는 인스턴스에서 공통적으로 사용하는 데이터입니다.
  MidgetCar SprintCar
이름 Midget Sprint
속력 140 160
마력 400 1000
@Getter
@Setter
public abstract class RaceCar {
    /**
     * Instrinsic (공유하는 객체가 모두 공통적으로 갖고있는 데이터)
     */
    private String name;
    private int speed;
    private int horsePower;

    /**
     * Extrinsic (외부에서 공통으로 사용하는 메소드)
     */
    abstract void moveCar(int currentX, int currentY, int newX, int newY);
}

 

MidgetCar (ConcreteFlyweight)

public class FlyweightMidgetCar extends RaceCar {
    public static int num;

    public FlyweightMidgetCar() {
        num++;
    }

    @Override
    void moveCar(int currentX, int currentY, int newX, int newY) {
        System.out.println("MidgetCar");
        System.out.println("X : " + newX);
        System.out.println("Y : " + newY);
    }
}

 

SprintCar (ConcreteFlyweight)

public class FlyweightSprintCar extends RaceCar {
    public static int num;

    public FlyweightSprintCar() {
        num++;
    }

    @Override
    void moveCar(int currentX, int currentY, int newX, int newY) {
        System.out.println("SprintCar");
        System.out.println("X : " + newX);
        System.out.println("Y : " + newY);
    }
}

 

CarFactory (FlyweightFactory)

  • 무거운 ConcreteFlyweight 의 경우에는, 인스턴스를 최대 한 개 까지만 생성한 뒤 공유할 수 있도록 합니다.
  • 아래의 코드에서는 HashMap 을 이용하여 문자열에 해당하는 인스턴스를 반환하도록 합니다.
public class CarFactory {
    private static Map<String, RaceCar> flyweights = new HashMap<>();

    public static RaceCar getRaceCar(String key) {
        if(flyweights.containsKey(key)) {
            return flyweights.get(key);
        }

        RaceCar raceCar;

        switch (key) {
            case "Midget":
                raceCar = new FlyweightMidgetCar();
                raceCar.setName("Midget Car");
                raceCar.setSpeed(140);
                raceCar.setHorsePower(400);
                break;
            case "Sprint":
                raceCar = new FlyweightSprintCar();
                raceCar.setName("Sprint Car");
                raceCar.setSpeed(160);
                raceCar.setHorsePower(1000);
                break;
            default:
                throw new IllegalArgumentException("Unsupported Car Type.");
        }
        flyweights.put(key, raceCar);
        return raceCar;
    }
}

 

Client (RaceCarClient)

  • 자동차보다 상대적으로 가벼운 인스턴스인 운전수의 경우에 대해서
    • 위치값 (X, Y) 에 대한 값을 갖고있도록 하여 RAM 을 최적화합니다.
public class RaceCarClient {
    private RaceCar raceCar;

    public RaceCarClient(String name) {
        raceCar = CarFactory.getRaceCar(name);
    }

    private int currentX = 0;
    private int currentY = 0;

    public void moveCar(int newX, int newY) {
        raceCar.moveCar(currentX, currentY, newX, newY);
        currentX = newX;
        currentY = newY;
    }
}

Usage

@Test
void test() {
    RaceCarClient raceCars[] = {
            new RaceCarClient("Midget"),
            new RaceCarClient("Midget"),
            new RaceCarClient("Midget"),
            new RaceCarClient("Midget"),
            new RaceCarClient("Sprint"),
            new RaceCarClient("Sprint")
    };

    raceCars[0].moveCar(1, 2);
    raceCars[1].moveCar(3, 4);
    raceCars[4].moveCar(5, 6);

    assertEquals(1, FlyweightMidgetCar.num);
    assertEquals(1, FlyweightSprintCar.num);
}

참고

 

'디자인패턴' 카테고리의 다른 글

퍼사드 패턴 (Facade Pattern)  (0) 2021.07.10
장식자 패턴 (Decorator Pattern)  (0) 2021.07.10
복합체 패턴 (Composite Pattern)  (0) 2021.06.19
브릿지 패턴 (Bridge Pattern)  (0) 2021.06.18
어댑터 패턴 (Adapter pattern)  (0) 2021.06.12