본문 바로가기

JAVA/디자인 패턴

[Design Pattern] Flyweight(플라이웨이트) 패턴이란?

반응형
구조 패턴(Structural Pattern)


Flyweight 패턴은 객체 지향 디자인 패턴 중 하나로, 메모리 사용량을 줄이고 성능을 개선하기 위해 사용하는 패턴입니다.

이 패턴은 많은 수의 비슷한 객체를 생성하는 경우에 유용합니다. 예를 들어, 게임에서 많은 수의 적 캐릭터가 있을 때, 모든 캐릭터가 동일한 이미지를 사용하는 경우가 있습니다. 이때 Flyweight 패턴을 사용하면 메모리 사용량을 줄이고 성능을 개선할 수 있습니다.

Flyweight 패턴은 객체를 두 가지 종류로 분류합니다. 첫 번째 종류는 Intrinsic(본질적) 객체이며, 이 객체는 공유될 수 있습니다. Intrinsic 객체는 외부에서 변경할 수 없는 고정된 상태를 가지고 있으며, 객체를 공유하는 것이 가능합니다.

두 번째 종류는 Extrinsic(외적) 객체입니다. 이 객체는 공유되지 않으며, 객체를 고유하게 만드는 데 사용됩니다. Extrinsic 객체는 Intrinsic 객체와 함께 사용되며, Intrinsic 객체가 변경되지 않는 한 여러 Extrinsic 객체에서 공유될 수 있습니다.

Flyweight 패턴은 객체를 생성하는 것이 비용이 높은 경우, 객체의 공유가 가능하다면 메모리 사용량을 줄이고 성능을 개선하는 데에 효과적입니다. Flyweight 패턴을 사용하면 같은 Intrinsic 객체를 공유함으로써 객체의 수를 줄이고, 메모리 사용량을 최적화할 수 있습니다.

 

 

Flyweight 패턴 예제

 

Flyweight 패턴을 구현하기 위해서는 다음과 같은 요소가 필요합니다.

  • Flyweight 인터페이스: Intrinsic 객체와 Extrinsic 객체를 구분하여 처리하는 메서드를 정의합니다.
  • ConcreteFlyweight 클래스: Flyweight 인터페이스를 구현하여 Intrinsic 객체를 정의합니다.
  • FlyweightFactory 클래스: Flyweight 객체를 생성하고 저장하고 반환하는 메서드를 정의합니다. 객체의 생성은 싱글톤 패턴을 사용하여 한 번만 이루어지도록 합니다.
  • Client 클래스: Flyweight 패턴을 사용하여 객체를 생성하는 메서드를 정의합니다.

Diagrams

 

Flyweight 인터페이스

 

public interface Shape {
    void draw();
}

 

 

ConcreteFlyweight 클래스

 

public class Circle implements Shape {
    private String color;
    private int x;
    private int y;
    private int radius;

    public Circle(String color) {
        this.color = color;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public void setRadius(int radius) {
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Circle: Draw() [Color : " + color + ", x : " + x + ", y :" + y + ", radius :" + radius);
    }
}

 

 

FlyweightFactory 클래스

 

public class ShapeFactory {
    private static final HashMap<String, Shape> circleMap = new HashMap<>();

    public static Shape getCircle(String color) {
        Circle circle = (Circle) circleMap.get(color);

        if (circle == null) {
            circle = new Circle(color);
            circleMap.put(color, circle);
            System.out.println("Creating circle of color : " + color);
        }

        return circle;
    }
}

 

 

Client 클래스

 

public class Main {
    private static final String[] colors = {"Red", "Green", "Blue"};

    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            Circle circle = (Circle) ShapeFactory.getCircle(getRandomColor());
            circle.setX(getRandomX());
            circle.setY(getRandomY());
            circle.setRadius(100);
            circle.draw();
        }
    }

    private static String getRandomColor() {
        return colors[(int) (Math.random() * colors.length)];
    }

    private static int getRandomX() {
        return (int) (Math.random() * 100);
    }

    private static int getRandomY() {
        return (int) (Math.random() * 100);
    }
}

 

위 예제에서는 Circle 클래스가 Flyweight 인터페이스를 구현하고, ShapeFactory 클래스가 FlyweightFactory 클래스 역할을 수행합니다. Client 클래스에서는 ShapeFactory 클래스를 사용하여 Circle 객체를 생성하고 그리는 메서드를 호출합니다.

새로운 색상의 경우 Circle 객체를 새로 생성하고 같은 색상 경우에는 circleMap에서 꺼내어 사용하여 메모리 사용량을 최적화 합니다.

실행 결과는 다음과 같습니다.

 

Creating circle of color : Green
Circle: Draw() [Color : Green, x : 78, y :93, radius :100
Creating circle of color : Red
Circle: Draw() [Color : Red, x : 22, y :95, radius :100
Circle: Draw() [Color : Red, x : 67, y :76, radius :100
Creating circle of color : Blue
Circle: Draw() [Color : Blue, x : 35, y :90, radius :100
Circle: Draw() [Color : Red, x : 0, y :93, radius :100
Circle: Draw() [Color : Green, x : 92, y :60, radius :100
Circle: Draw() [Color : Green, x : 70, y :31, radius :100
Circle: Draw() [Color : Blue, x : 75, y :28, radius :100
Circle: Draw() [Color : Blue, x : 36, y :36, radius :100
Circle: Draw() [Color : Red, x : 85, y :83, radius :100
Circle: Draw() [Color : Blue, x : 77, y :90, radius :100
Circle: Draw() [Color : Red, x : 56, y :16, radius :100
Circle: Draw() [Color : Green, x : 69, y :55, radius :100
Circle: Draw() [Color : Red, x : 64, y :82, radius :100
Circle: Draw() [Color : Red, x : 2, y :6, radius :100
Circle: Draw() [Color : Red, x : 8, y :71, radius :100
Circle: Draw() [Color : Red, x : 87, y :95, radius :100
Circle: Draw() [Color : Green, x : 62, y :78, radius :100
Circle: Draw() [Color : Green, x : 40, y :33, radius :100
Circle: Draw() [Color : Blue, x : 46, y :28, radius :100

 

반응형