개발/디자인패턴

[Java][디자인 패턴] 12. 플라이웨이트 패턴 (Flyweight Patten)

nova_dev 2022. 3. 16. 00:00
반응형

디자인패턴
[Java][디자인 패턴] 12. 플라이웨이트 패턴 (Flyweight Pattern)

플라이웨이트 패턴은 객체를 공유하여 객체를 재사용해서 시스템을 절약할 수 있는 디자인 패턴이다.
fly(가볍다) + weight (무게) = 중복되는 코드의 객체를 공유해서 메모리를 적게 할당해서 무게가 가벼움

 플라이웨이트 패턴이란?

  • 플라이웨이트 패턴은 객체의 할당을 적게 하기 위한 패턴이며, 한 번 할당한 자원을 재사용함으로써 메모리를 관리한다.
  • 플라이웨이트 패턴은 중복을 제거하고 공유를 통해 자원을 효율적으로 사용한다.
  • 플라이웨이트 패턴은 보다 효율적인 공유 객체를 관리하기 위해 별도 저장소를 갖고 있는데 이를 공유 저장소라고 한다.
  • 플라이웨이트 패턴은 팩토리 클래스에 공유 저장소를 추가하여 객체의 중복 생성 동작을 제한한다.
  • 플라이웨이트 패턴은 무분별하게 객체를 생성하지 않고 기존 객체를 참조함으로써 중복을 방지한다. 이렇게 기존의 객체를 사용한 후 삭제하지 않고 재사용 혹은 공유할 경우 메모리 자원을 절약하는 것과 동시에 객체의 생성하는 자원과 시간도 같이 절약할 수 있다.
  • 공유 객체가 상태 값에 종속적인 상태면 플라이웨이트 패턴으로 공유할 수 없다. 객체 상태가 변경됨으로써 참조하는 다른 객체에 사이드 이펙트 효과가 발생하기 때문이다.
  • 대량의 객체를 생성 및 관리할 경우 플라이웨이트 패턴은 매우 유용한 대안이 될 수 있다. 또한 관리하는 객체의 수가 많아서 처리하기 힘든 경우에도 효과적이다.

 플라이웨이트 패턴 구성요소

  • Flyweight
    • 공유에 사용할 클래스들의 인터페이스를 선언
  • ConcreteFlyweight
    • Flyweight의 구체 클래스 (실제 공유될 객체)
  • FliweightFactory
    • Flyweight 인스턴스를 생성 또는 공유해주는 역할
  • Client
    • 플라이웨이트틀 사용하는 사용자

 플라이웨이트 예제 코드 구성

플라이웨이트 패턴으로 구현한 keyboard

책에 있는 예제는 조금 와닿지 않아서 공유 객체로 들고 있을 만한 친구가 뭐가 있을까 고민하다가 키보드 객체들을 공유 풀에 가지고 있는 것으로 생각하고 코드를 짜 보았다. button을 구현하고 있는 Keyboard 구현 클래스들이 있고, 이러한 Keyboard 들을 공유 풀 형태로 Factory가 가지고 서비스들이 해당 키보드 클래스가 필요할 때 새로 생성해서 쓰는 게 아니라 키값으로 클래스를 가져와서 사용할 수 있도록 만들었다.

이런 패턴을 보면서, 스프링 컨테이너에서 Bean 객체를 관리할 때에도 플라이웨이트 패턴을 응용해서 풀에 빈 객체들을 미리 생성해서 가지고 있는것이 아닌가 하는 생각을 했다. (물론 default 빈 스코프인 싱글톤으로 생성했을 경우에)

 플라이웨이트 패턴 코드

1.Keyboard 인터페이스

public interface Keyboard {
    void button();
}

2. Keyboard 구현 클래스 (A, B, C, D)

public class KeyboardA implements Keyboard {
    @Override
    public void button() {
        System.out.println("A");
    }
}
public class KeyboardB implements Keyboard {
    @Override
    public void button() {
        System.out.println("B");
    }
}
public class KeyboardC implements Keyboard {
    @Override
    public void button() {
        System.out.println("C");
    }
}
public class KeyboardD implements Keyboard {
    @Override
    public void button() {
        System.out.println("D");
    }
}

3. Keyboard 클래스들을 재생성하지 않고 사용하기 위해 공유 풀에 가지고 있는 팩토리 클래스

public class Factory {
    private final Map<String, Keyboard> pool;

    public Factory() {
        this.pool = new HashMap<>();
        pool.put("A", new KeyboardA());
        pool.put("B", new KeyboardB());
        pool.put("C", new KeyboardC());
        pool.put("D", new KeyboardD());
    }

    public Keyboard getButton(String button) {
        return pool.get(button);
    }
}

4. Keyboard 테스트 코드

class KeyboardTest {
    @Test
    @DisplayName("키보드 부호 테스트")
    void morseTest() {
        Factory factory = new Factory();
        factory.getButton("A").button();
        factory.getButton("B").button();
        factory.getButton("C").button();
        factory.getButton("D").button();

    }
}

 

 Github 코드

Github 예제 코드 링크

Github 예제 테스트 코드 링크

참고 자료

 

 

 

 

 

반응형