濱田です!
今回も前回に引き続きGoFのデザインパターンを紹介します。
みなさんはクラス設計もしくは運用時にこんな事を思った事はありませんか?
「大量にクラスをインスタンス化したいのにリソースがたりない・・・」
例えば学生の情報を管理しようと思った場合オブジェクト指向を使ったクラス設計をすると学生オブジェクトが学生の人数分必要になります。こういった場合コンストラクターとセッター・ゲッターの簡単なクラスでも1000人学生がいれば1000個のインスタンスが必要になり、インスタンスを保持するためのリソースと保持するためのリソースが学生の人数分必要になります。
こんな時に適用するデザインパターンがFlyweightパターンです。
日本語で言うと「フライ級」って訳すそうです。
ではでは、今回も3つのチェックポイントにそって説明します。
■目的
小さくて軽いオブジェクトをいっぱい作りたいけどコストを抑えたい!
■背景
オブジェクト生成と保持のコストを抑えたい。
■効果
あらかじめインスタンス化しておいたオブジェクトをグローバル領域に保持しておき必要におうじて検索キーワードで必要な属性値を持つオブジェクトを取得することにより一度に保持するオブジェクトの数を減らす。
ではコードを見てみましょう。
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
class Flyweight{
public static void main(String[] aa){
StudentFactory sf = new StudentFactory();
//プール用変数
List<Student> stArray= new ArrayList<Student>();
stArray.add(sf.get("1組","熊谷"));
stArray.add(sf.get("2組","橋本"));
for(Student s : stArray){
s.print();
System.out.println(s);
}
stArray.clear();
stArray.add(sf.get("1組","橋本"));
stArray.add(sf.get("2組","熊谷"));
for(Student s : stArray){
s.print();
System.out.println(s);
}
}
}
class StudentFactory {
HashMap pool;
StudentFactory(){
this.pool = new HashMap();
}
Student get(String course,String name){
Student st =(Student) this.pool.get(course);
//まだcourse用共有オブジェクトを作っていなければ
//新しく作ってHashMapに格納します。
if(st == null) {
st = new Student(course);
this.pool.put(course, st);
}
//共有オブジェクトのname変数を書き換えてから返却します。
st.setName(name);
return st;
}
}
class Student {
private String name;
private String course;
Student(String c){
this.course = c;
}
public void setName(String name){
this.name = name;
}
public void print(){
System.out.print(this.course + " -> ");
System.out.println(this.name);
}
}
実行結果は以下のようになります。
1組 -> 熊谷
Student@1a758cb
2組 -> 橋本
Student@1b67f74
1組 -> 橋本
Student@1a758cb
2組 -> 熊谷
Student@1b67f74
オブジェクトが4つあるように見えますが実際のオブジェクトは2つしかない所がFlyweightパターンのミソになります。
Javaだとガベージコレクションがしっかりしているのであまり使いどころのないデザインパターンですが、Permanen領域が不足するような場合にFlyweightパターンの発想でオブジェクトの共有化をはかるのも一つの手になると思います。