Java 디자인 모드의 공유 모드/향원 모드(Flyweight 모드) 소개

Flyweight 정의: 같은 내용을 가진 소류의 지출을 피하고 (예를 들어 메모리 소모)을 공유하도록 합니다.
공유 모드/향원 모드를 사용하는 이유
대상 언어를 대상으로 하는 원칙은 모든 것이 대상이다. 그러나 만약에 진정으로 사용한다면 때로는 대상 수가 매우 방대하게 보일 수도 있다. 예를 들어 문자 처리 소프트웨어, 만약에 모든 문자를 하나의 대상으로 한다면 수천 글자, 대상 수는 수천 글자로 의심할 여지없이 메모리를 소모한다. 그러면 우리는'동일존이'를 찾아 이러한 대상 그룹의 공통점을 찾아내고 하나의 원류를 설계하고 공유될 수 있는 종류를 봉인해야 한다. 또한그리고 일부 특성은 응용(context)에 달려 공유할 수 없는 것이다. 이것 또한 Flyweight에서 두 가지 중요한 개념인 내부 상태 intrinsic와 외부 상태 extrinsic의 구분이다.
백점은 먼저 하나의 원시 모델을 만든 다음에 서로 다른 장소와 환경에 따라 각 특징을 가진 구체적인 모델이 생기는 것이다. 분명히 여기서 서로 다른 새로운 대상이 생겨야 하기 때문에 Flyweight 모델에는 Factory 모델이 자주 나타난다.Flyweight의 내부 상태는 공유하는 데 사용되며, Flyweight factory는 내부 상태의 대상을 저장하기 위해 Flyweight pool(패턴 탱크)을 유지하는 것을 책임진다.
Flyweight 모드는 프로그램의 효율과 성능을 향상시키는 모드로 프로그램의 운행 속도를 크게 높일 수 있다.응용 장소가 많습니다. 예를 들어 데이터베이스에서 일련의 문자열을 읽으려면 이 문자열 중 많은 것이 중복됩니다. 그러면 우리는 이 문자열을 Flyweight 탱크 (pool) 에 저장할 수 있습니다.
공유 모드/향원 모드 사용 방법
Flyweight 추상적인 인터페이스부터 시작하겠습니다.

public interface Flyweight{
 public void operation( ExtrinsicState state );
}
// ( )
public interface ExtrinsicState { }
다음은 인터페이스의 구체적인 실현(Concrete Flyweight)이고 내부 상태에 메모리 공간을 늘리기 위해 Concrete Flyweight는 공유할 수 있어야 하며 저장된 모든 상태는 내부(intrinsic)여야 한다. 즉, Concrete Flyweight는 응용 환경과 무관해야 한다.

public class ConcreteFlyweight implements Flyweight {
 private IntrinsicState state;
 public void operation( ExtrinsicState state ){
   //
 }
}
물론 모든 Flyweight가 하위 클래스를 구체적으로 실현하려면 공유되어야 하는 것은 아니기 때문에 또 다른 공유하지 않는 Concrete Flyweight도 있다.

public class UnsharedConcreteFlyweight implements Flyweight {
 public void operation( ExtrinsicState state ) { }
}
Flyweight factory는 Flyweight 탱크 (내부 상태 저장) 를 유지하는 것을 책임집니다. 클라이언트가 Flyweight 공유를 요청할 때 이 factory는 우선 탱크에 적용될 수 있는 것이 있는지 검색합니다. 만약에factory는 이 대상을 간단하게 되돌려줍니다. 그렇지 않으면 새로운 대상을 만들어서 탱크에 넣고 이 대상 탱크로 되돌려줍니다.

public class FlyweightFactory {
 //Flyweight pool
 private Hashtable flyweights = new Hashtable();
 public Flyweight getFlyweight( Object key ) {
  Flyweight flyweight = (Flyweight) flyweights.get(key);
  if( flyweight == null ) {
   // ConcreteFlyweight
   flyweight = new ConcreteFlyweight();
   flyweights.put( key, flyweight );
  }
   return flyweight;
 }
}
이로써 Flyweight 모드의 기본 프레임워크가 준비되었습니다. 어떻게 호출하는지 살펴보겠습니다.

FlyweightFactory factory = new FlyweightFactory();
Flyweight fly1 = factory.getFlyweight( "Fred" );
Flyweight fly2 = factory.getFlyweight( "Wilma" );
......
호출을 보면 순수한 Factory가 사용하는 것 같지만 오묘함은 Factory의 내부 설계에 있다.
XML과 같은 데이터 소스에 Flyweight 모드 적용
위에서 언급한 바와 같이 데이터 원본에서 문자열을 대량으로 읽으면 중복되는 것이 틀림없다. 그러면 우리는 Flyweight 모드를 사용하면 효율을 높일 수 있다. 음반 CD를 예로 들면 XML 파일에 여러 개의 CD 자료를 저장할 수 있다.
CD당 필드는 다음과 같습니다.
1. 개봉 날짜(year)
2. 가창자 이름 등 정보(artist)
3. 음반 트랙 (title)
그 중에서 가수의 이름이 중복될 수 있다. 즉, 같은 가수의 여러 시기마다 다른 곡의 CD가 있을 수 있다는 것이다.우리는 노래 부르는 사람의 이름을 공유할 수 있는 Concrete Flyweight로 삼을 것이다.다른 두 필드는 UnsharedConcreteFlyweight로 사용됩니다.
먼저 데이터 소스 XML 파일의 내용을 살펴보겠습니다.

<?xml version="1.0"?>
<collection>

<cd>
<title>Another Green World</title>
<year>1978</year>
<artist>Eno, Brian</artist>
</cd>

<cd>
<title>Greatest Hits</title>
<year>1950</year>
<artist>Holiday, Billie</artist>
</cd>

<cd>
<title>Taking Tiger Mountain (by strategy)</title>
<year>1977</year>
<artist>Eno, Brian</artist>
</cd>
.......

</collection>

위의 예를 들어 CD는 3장뿐이지만 CD는 대량의 중복된 소류로 볼 수 있다. 왜냐하면 그 성분은 세 개의 필드만 있고 중복된 것이 있기 때문이다.
CD는 위의 Flyweight 인터페이스와 유사합니다.

public class CD {
 private String title;
 private int year;
 private Artist artist;

 public String getTitle() {return title;}
 public int getYear() {return year;}
 public Artist getArtist() {return artist;}

 public void setTitle(String t){title = t;}
 public void setYear(int y){year = y;}
 public void setArtist(Artist a){artist = a;}
}

"노래자 이름"을 공유할 수 있는 ConcreteFlyweight:

public class Artist {
 //
 private String name;

 // note that Artist is immutable.
 String getName(){return name;}

 Artist(String n){
     name = n;
    }
}

Flyweight factory를 다시 한 번 살펴보겠습니다. 위에 공유할 수 있는 Concrete Flyweight: Artist를 만드는 데 사용됩니다.

public class ArtistFactory {
 Hashtable pool = new Hashtable();
 Artist getArtist(String key){
  Artist result;
  result = (Artist)pool.get(key);
  //// Artist
  if(result == null) {
   result = new Artist(key);
   pool.put(key,result);  
  }
  return result;
    }
}
수천 장, 심지어 더 많은 CD가 있을 때, Flyweight 모드는 더 많은 공간을 절약하고, 공유하는 flyweight가 많을수록, 공간 절약도 커진다.

좋은 웹페이지 즐겨찾기