Flyweight

GamSa Ham·2022년 10월 24일
0

GoF디자인패턴

목록 보기
9/22

의도 :
공유를 통해 많은 수의 소립 객체들을 효과적으로 지원함

동기 :

  • 플라이급 객체는 공유 가능한 객체로 여러 비슷한 상황에서 사용 가능
  • 각각의 상황에서는 독립적인 객체로 동작
  • 따라서 같은 것을 놓고 상황에 따라 다른 특징으로 정의할 수 없음
    =>본질적 상태와 부가적 상태의 구분
    -본질적 상태 ; 플라이급 객체에 저장되어야 하며 상황과 상관없는 본질적 특성 정보들
    
    -부가적 상태 ;  플라이급 객체가 사용될 상황에 따라 달라질 수 있고 상황에 종속적이므로 공유 될 수 없는 정보들

예) 문서 편집기에서 각 글자
=>문자 하나하나를 객체로 관리하려면 비용이 많이 듦

본질적 상태 - 문자 코드
부가적 상태 - 문서 위치, 인쇄 스타일

각각의 글자를 인스턴스로 갖는 것이 아니라 각 글자들이 나타날 때마다 플라이급 객체의 공유된 풀에 존재하는 인스턴스에 대한 참조자를 갖도록 관리
=>인스턴스를 매번 생성하지 않고 만들어진 것을 공유하여 사용함

활용성 :

  • 응용프로그램이 대량의 객체를 사용해야 할 때
  • 객체의 수가 너무 많아져 저장 비용이 너무 높아질 때
  • 대부분의 객체 상태를 부가적인 것으로 만들 수 있을 때
  • 부가적인 속성들을 제거한 후 객체의 많은 묶음이 비교적 적은 수의 공유된 객체로 대체될 수 있을 때 (=부가적 속성은 다르되 본질이 다른 것은 아닌 경우)
  • 식별자가 있는 경우 서로 다른 객체로 구별해야 한다는 의미이므로 플라이급 패턴을 사용할 수 없음

참여자 :

  • Flyweight - Flyweight가 받아들일 수 있고 부가적 상태에서 동작해야 하는 인터페이스 선언(싱글턴)
  • ConcreteFlyweight - Flyweight 인터페이스를 구현하고 본질적 상태에 대한 저장소
    공유할 수 있어야 하므로 관리하는 어떤 상태라도 본질적인 것이어야 함
  • UnsharedConcreteFlyweight - 모든 플라이급 서브클래스들이 공유될 필요 없기 때문에 공유할 수 있지만 강제하지 않는 요소
  • FlyweightFactory - 플라이급 객체를 생성하고 관리하며 제대로 공유되도록 보장함
    사용자가 플라이급 객체 요청 시 이미 존재하는 인스턴스를 제공하거나 만약 존재하지 않는다면 새로 생성
  • Client - 플라이급 객체에 대한 참조자를 관리함 플라이급 객체의 부가적 상태를 저장
package Flyweight;

public class Flyweight {
	
	public Flyweight(String data) {
		this.data = data;
	}
	
	private String data;
	
	public String getData() {
		return data;
	}

}
package Flyweight;

import java.util.Map;
import java.util.TreeMap;

public class FlyweightFactory {

	Map<String, Flyweight> pool;
	
	public FlyweightFactory() {
		pool = new TreeMap<>();
	}
	
	public Flyweight getFlyweight(String key) {
		
		Flyweight flyweight = pool.get(key);
		
		if(flyweight == null) {
			flyweight = new Flyweight(key);
			pool.put(key, flyweight);
			
			System.out.println("새로 생성" + key);
		} else {
			System.out.println("재사용 " + key);
		}
		
		return flyweight;
		
	}
	
}
package Flyweight;

public class Main {

	public static void main(String[] args) {

		FlyweightFactory factory = new FlyweightFactory();
		
		Flyweight flyweight = factory.getFlyweight("A");
		
		System.out.println(flyweight);
		
		flyweight = factory.getFlyweight("A");
		
		System.out.println(flyweight);
		
	}
}
새로 생성A
Flyweight.Flyweight@15db9742
재사용 A
Flyweight.Flyweight@15db9742

협력방법 :

  • 플라이급 객체가 기능을 수행하는 데 필요한 상태가 본질적인 것인지 부가적인 것인지 구분
  • 본질적 상태는 ConcreteFlyweight에 저장, 부가적인 상태는 사용자가 저장하거나 연산되어야 하는 다른 상태로 관리해야 함
  • 사용자는 연산을 호출할 때 자신에게만 필요한 부가적 상태를 플라이급 객체에 매개변수로 전달함
  • 사용자는 ConcreteFlyweight의 인스턴스를 직접 만들 수 없고 FlyweightFactory 객체에서 얻어야 함

결과 :
예전에 모두 본질적인 상태로 저장되어 있던 것을 부가적인 상태로 만듦

  • 부가적인 상태의 연산과 전송에 드는 런타임 비용 추가
  • 플라이급 객체의 공유를 통해 저장소 절약
    => 더 많은 Flyweight가 공유될수록, 공유할 상태가 많아질수록 저장소는 절약됨

사용예 :

  • 플라이급 패턴은 복합체 패턴과 조합하여 그래프와 같이 계층적 구조를 모델링하는 데에 사용함
    ⇒ 플라이급 단말 노드들은 자신의 부모에 대한 포인터를 저장할 수 없기 때문에 부모 포인터를 부가적 상태의 일부로 플라이급 객체에 매개변수로 전달해야 함
  • 상태 패턴, 전략 패턴을 플라이급 객체로 구현할 수 있음
profile
안녕하세요. 자바를 좋아하고 디자인 패턴, Refactoring, Clean Code에 관심이 많은 백엔드 개발자입니다.

0개의 댓글