플라이웨이트 패턴

정선호·2023년 5월 24일
0

Design Patterns

목록 보기
17/24

관련 영상

플라이웨이트 패턴

  • 각 객체에 모든 데이터를 유지하는 대신 여러 객체들 간에 상태의 공통 부분들을 공유하여 사용할 수 있는 RAM에 더 많은 객체들을 포함할 수 있도록 하는 구조 디자인 패턴
    • 오브젝트의 일부 상태 정보는 공유될 수 있는데 이를 외부 자료구조에 저장하여 플라이웨이트 오브젝트가 잠깐 동안 사용할 수 있도록 전달.
  • 플라이웨이트 패턴은 단지 최적화에 불과
    • 이 패턴을 적용하기 전 프로그램이 RAM 소비 문제가 있는지 확인하고, 이 문제가 다른 의미있는 방법으로 해결될 수 없는지도 확인하여라
  • 플라이웨이트는 불변해야 한다
    • 같은 플라이웨이트 객체가 다른 콘텍스트들에서 사용될 수 있으므로 해당 플라이웨이트 객체의 상태를 수정할 수 없는지 확인해야 한다.
    • 플라이웨이트는 생성자 매개변수들을 통해 상태를 한 번만 초기화해야 한다. 또 setter 또는 public 필드들을 다른 객체들에 노출해서는 안 된다다.
  • 플라이웨이트 팩토리
    • 다양한 플라이웨이트들에 보다 편리하게 액세스하기 위해 기존 플라이웨이트 객체들의 풀을 관리하는 팩토리 메서드를 생성할 수 있다.
    • 이 메서드는 클라이언트에서 원하는 플라이웨이트의 고유한 상태를 받아들이고 이 상태와 일치하는 기존 플라이웨이트 객체를 찾고 발견되면 반환한다. 아니면 새 플라이웨이트를 생성해풀에 추가한다.

플라이웨이트 구조

  • 플라이웨이트(Flyweight) 클래스
    • 여러 객체들간에 공유할 수 있는 원래 객체의 상태의 부분이 포함된다
    • 같은 플라이웨이트 객체가 다양한 콘텍스트에서 사용될 수 있다
    • 플라이웨이트 내부에 저장된 상태를 고유한(intrinsic) 상태라고 하며, 플라이웨이트 메서드에 전달된 상태를 공유한(extrinsic) 상태라고 한다
  • 콘텍스트(Context) 클래스
    • 공유한 상태를 포함하며, 이 상태는 모든 원본 객체들에서 고유하다
    • 콘텍스트가 플라이웨이트 객체 중 하나와 쌍을 이루면 원래 객체의 전채 상태를 나타낸다
  • 클라이언트(Client)
    • 플라이웨이트들의 공유된 상태를 저장하거나 계산한다.
    • 클라이언트의 관점에서 플라이웨이트는 일부 콘텍스트 데이터를 그의 메서드들의 매개변수들에 전달하여 런타임에 설정될 수 있는 템플릿 객체이다
  • 플라이웨이트 팩토리(FlyweightFactory)
    • 기존 플라이웨이트들의 풀을 관리
    • 클라이언트들은 플라이웨이트들을 직접 만들지 않는 대신 원하는 플라이웨이트의 고유한 상태의 일부를 전달하여 공장을 호출
    • 팩토리는 이전에 생성된 플라이웨이트들을 살펴보고 검색 기준과 일치하는 기존 플라이웨이트를 반환하거나 기준에 맞는 플라이웨이트가 발견되지 않으면 새로 생성

플라이웨이트의 적용

  • 프로그램이 많은 수의 객체들을 지원해야 해서 사용할 수 있는 RAM을 거의 다 사용했을 때만 사용
    • 앱이 수많은 유사 객체들을 생성할 때
    • 이것이 대상 장치에서 사용할 수 있는 모든 RAM을 소모할 때
    • 이 객체들에 여러 중복 상태들이 포함되어 있으며, 이 상태들이 추출된 후 객체 간에 공유될 수 있을 때 유용하다

다른 패턴과의 관계

  • RAM을 절약하기 위하여 복합체 패턴 트리의 공유된 잎 노드들을 플라이웨이트들로 구현할 수 있다.
  • 플라이웨이트는 작은 객체들을 많이 만드는 방법을 보여 주는 반면 퍼사드 패턴은 전체 하위 시스템을 나타내는 단일 객체를 만드는 방법을 보여 준다.
  • 만약 객체들의 공유된 상태들을 단 하나의 플라이웨이트 객체로 줄일 수 있다면 플라이웨이트는 싱글턴과 유사해질 수 있다. 그러나 이 패턴들에는 두 가지 근본적인 차이점이 있다:
    • 싱글턴은 인스턴스가 하나만 있어야 한다. 반면에 플라이웨이트 클래스는 여러 고유한 상태를 가진 여러 인스턴스를 포함할 수 있다.
    • 싱글턴 객체는 변할 수 있다 (mutable). 플라이웨이트 객체들은 변할 수 없다 (immutable).

플라이웨이트를 이용한 나무심기

  • 플라이웨이트
public class Tree {

    // 나무는 아래와 같이 3개 정보를 가지고 있습니다.
    private String color;
    private int x;
    private int y;

    //색상으로만 생성자를 만들어줄게요.
    public Tree(String color) {
        this.color = color;
    }

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

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

    //나무를 심을 때
    public void install(){
        System.out.println("x:"+x+" y:"+y+" 위치에 "+color+"색 나무를 설치했습니다!");
    }
}
  • 플라이웨이트 팩토리
public class TreeFactory {
    //HashMap 자료구조를 활용해서 만들어진 나무들을 관리해볼게요
    public static final HashMap<String, Tree> treeMap = new HashMap<>();
    
   
    public static Tree getTree(String treeColor){
        //Map에 입력받은 색상의 나무가 있는지 찾습니다. 있으면 그 객체를 제공합니다.
        Tree tree = (Tree)treeMap.get(treeColor); 

       //만약 아직 같은 색상의 나무가 Map에 없다면 새로 객체를 생성해 제공합니다.
        if(tree == null){
            tree = new Tree(treeColor);
            treeMap.put(treeColor, tree);
            System.out.println("새 객체 생성");
        }

        return tree;
    }
}
  • 클라이언트
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.println("원하는 색을 입력해주세요 :)");
        for(int i=0;i<10;i++){
            //나무 색 입력받기
            String input = scanner.nextLine();
            //팩토리에서 나무 하나 공급받기
            Tree tree = (Tree)TreeFactory.getTree(input);
            //나무 x,y 설정하고
            tree.setX((int) (Math.random()*100));
            tree.setY((int) (Math.random()*100));
            //나무 설치하기
            tree.install();
        }

    }
}
profile
학습한 내용을 빠르게 다시 찾기 위한 저장소

0개의 댓글