Comments
Transcript
第20章 Flyweight Flyweightパターンとは サンプルプログラム 「大きな
2015/6/28 Flyweightパターンとは • Flyweight とは、英語で「フライ級」 – ボクシングで最も軽い階級 ⇨ オブジェクト(メモリの使用量)を「軽く」するもの 第20章 Flyweight ~同じものを共有して無駄をなくす~ • Flyweightは、「インスタンスをできるだけ共有 させて、無駄にnewしない」 深澤研究室 M0 1w120399-6 西田 和馬 – インスタンスの生成「new」は、メモリを確保 – 多くの「new」はメモリの使用量の増加 1 サンプルプログラム 2 「大きな文字」のtxtファイル big0.txt • コマンドラインで入力された値・文字を大きな文字で出力 big1.txt – 大きな文字を構成するデータはtxtファイルで用意 • 数字は「0~9」 • 文字は ” - ” のみ 同様に、 big2.txt~ big8.txtも用意 – 目的のファイルがない場合(” - ”以外の文字) • 文字の後に ” ? ”をつけたものをフォントデータとして出力 big-.txt big9.txt 3 サンプルプログラムのクラス図 4 BigCharクラス import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; 大きな文字を表現するクラス public class BigChar { private char charname; // 文字の名前 private String fontdata; // 大きな文字を表現する文字列('#' '.' '¥n'の列) public BigChar(char charname) { // コンストラクタ this.charname = charname; try { BufferedReader reader = new BufferedReader( new FileReader("big" + charname + ".txt") ); String line; StringBuffer buf = new StringBuffer(); while ((line = reader.readLine()) != null) { buf.append(line); buf.append("¥n"); } reader.close(); this.fontdata = buf.toString(); } catch (IOException e) { this.fontdata = charname + "?"; } } public void print() { // 大きな文字を表示する System.out.print(fontdata); } } ファイルから大きな文字のテキスト読み込み lineにファイル内容を一行書き、これをbufに追加 fontdataに作成した文字列(テキスト内容)を格納 大きな文字はメモリ消費量が多い ⇨ BigCharのインスタンス共有を目指す 5 6 1 2015/6/28 BigCharFactoryクラス BigCharFactoryクラス BigCharのインスタンスを共有しながら生成するクラス BigCharのインスタンスを共有しながら生成するクラス import java.util.HashMap; import java.util.HashMap; public class BigCharFactory { // すでに作ったBigCharのインスタンスを管理 private HashMap pool = new HashMap(); // Singletonパターン private static BigCharFactory singleton = new BigCharFactory(); // コンストラクタ private BigCharFactory() { } // 唯一のインスタンスを得る public static BigCharFactory getInstance() { return singleton; } // BigCharのインスタンス生成(共有) public synchronized BigChar getBigChar(char charname) { BigChar bc = (BigChar)pool.get("" + charname); if (bc == null) { bc = new BigChar(charname); // BigCharのインスタンスを生成 pool.put("" + charname, bc); } return bc; } } public class BigCharFactory { // すでに作ったBigCharのインスタンスを管理 private HashMap pool = new HashMap(); // Singletonパターン private static BigCharFactory singleton = new BigCharFactory(); // コンストラクタ private BigCharFactory() { } // 唯一のインスタンスを得る public static BigCharFactory getInstance() { return singleton; } // BigCharのインスタンス生成(共有) public synchronized BigChar getBigChar(char charname) { BigChar bc = (BigChar)pool.get("" + charname); if (bc == null) { bc = new BigChar(charname); // BigCharのインスタンスを生成 pool.put("" + charname, bc); } return bc; } } 文字列→インスタンスの対応関係を管理 ・poolに目的の文字のインスタンスがない場合 引数charnameで与えられた文字に対応する BigCharのインスタンスを作成 ・ Singletonパターン - BigCharFactoryのインスタンスは1つで良い ・pool:これまでに作ったインスタンスを格納 ・pool内から目的の文字のインスタンスを検索しbcに格納 ⇨ ない場合は、bc = null 7 poolに作成したインスタンスを登録 BigCharFactoryクラス BigStringクラス BigCharのインスタンスを共有しながら生成するクラス BigCharを集めて作った「大きな文字列」を表すクラス import java.util.HashMap; public class BigCharFactory { // すでに作ったBigCharのインスタンスを管理 private HashMap pool = new HashMap(); // Singletonパターン private static BigCharFactory singleton = new BigCharFactory(); // コンストラクタ private BigCharFactory() { } // 唯一のインスタンスを得る public static BigCharFactory getInstance() { return singleton; } // BigCharのインスタンス生成(共有) public synchronized BigChar getBigChar(char charname) { BigChar bc = (BigChar)pool.get("" + charname); if (bc == null) { bc = new BigChar(charname); pool.put("" + charname, bc); 既に同じ文字のインスタンスを作っている場合 // BigCharのインスタンスを生成 } return bc; 新しいインスタンス を作らない } 8 public class BigString { // 「大きな文字」の配列 private BigChar[] bigchars; BigCharのインスタンスを保持 // コンストラクタ public BigString(String string) { bigchars = new BigChar[string.length()]; コマンドラインで指定した文字 BigCharFactory factory = BigCharFactory.getInstance(); for (int i = 0; i < bigchars.length; i++) { bigchars[i] = factory.getBigChar(string.charAt(i)); } 文字列stringのi番目の文字を返す } (先頭は0文字目) // 表示 public void print() { for (int i = 0; i < bigchars.length; i++) { i番目の文字に対応するインスタンスを生成 bigchars[i].print(); } } } 9 } 10 プログラムの流れ Mainクラス 動作テスト用のクラス public class Main { public static void main(String[] args) { if (args.length == 0) { System.out.println("Usage: java Main digits"); System.out.println("Example: java Main 1212123"); System.exit(0); } BigString bs = new BigString(args[0]); bs.print(); } } 入力例 BigStringクラス public class BigString { // 「大きな文字」の配列 private BigChar[] bigchars; // コンストラクタ public BigString(String string) { bigchars = new BigChar[string.length()]; BigCharFactory factory = BigCharFactory.getInstance(); for (int i = 0; i < bigchars.length; i++) { bigchars[i] = factory.getBigChar(string.charAt(i)); } } // 表示 public void print() { for (int i = 0; i < bigchars.length; i++) { bigchars[i].print(); } } } 1212123 出力 Mainクラス public class Main { public static void main(String[] args) { if (args.length == 0) { System.out.println("Usage: java Main digits"); System.out.println("Example: java Main 1212123"); 実行例 java Main 1212123 System.exit(0); } BigString bs = new BigString(args[0]); bs.print(); } } 11 12 2 2015/6/28 プログラムの流れ BigCharFactoryクラス import java.util.HashMap; 1 } // BigCharのインスタンス生成(共有) public synchronized BigChar getBigChar(char charname) { BigChar bc = (BigChar)pool.get("" + charname); if (bc == null) { // BigCharのインスタンスを生成 bc = new BigChar(charname); pool.put("" + charname, bc); BigCharクラス BigCharFactoryクラス public class BigString { // 「大きな文字」の配列 private BigChar[] bigchars; // コンストラクタ public BigString(String string) { bigchars = new BigChar[string.length()]; BigCharFactory factory = BigCharFactory.getInstance(); for (int i = 0; i < bigchars.length; i++) { bigchars[i] = factory.getBigChar(string.charAt(i)); } } // 表示 public void print() { for (int i = 0; i < bigchars.length; i++) { bigchars[i].print(); } } } 1212123 public class BigCharFactory { private HashMap pool = new HashMap(); private static BigCharFactory singleton = new BigCharFactory(); private BigCharFactory() { } // 唯一のインスタンスを得る public static BigCharFactory getInstance() { return singleton; プログラムの流れ BigStringクラス import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.HashMap; public class BigCharFactory { private HashMap pool = new HashMap(); private static BigCharFactory singleton = new BigCharFactory(); private BigCharFactory() { } // 唯一のインスタンスを得る public static BigCharFactory getInstance() { return singleton; 1 1 } // BigCharのインスタンス生成(共有) public synchronized BigChar getBigChar(char charname) { 1 BigChar bc = (BigChar)pool.get("" + charname); if (bc == null) { // BigCharのインスタンスを生成 bc = new BigChar(charname); pool.put("" + charname, bc); } return bc; } return bc; } } } } public class BigChar { private char charname; // 文字の名前 private String fontdata; public BigChar(char charname) { // コンストラクタ this.charname = charname; try { BufferedReader reader = new BufferedReader( new FileReader("big" + charname + ".txt") ); String line; StringBuffer buf = new StringBuffer(); while ((line = reader.readLine()) != null) { buf.append(line); buf.append("¥n"); } reader.close(); this.fontdata = buf.toString(); } catch (IOException e) { this.fontdata = charname + "?"; } } public void print() { // 大きな文字を表示する System.out.print(fontdata); } } 13 プログラムの流れ 14 プログラムの流れ BigCharクラス BigCharFactoryクラス BigCharFactoryクラス import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.HashMap; public class BigCharFactory { private HashMap pool = new HashMap(); private static BigCharFactory singleton = new BigCharFactory(); private BigCharFactory() { } // 唯一のインスタンスを得る public static BigCharFactory getInstance() { return singleton; } // BigCharのインスタンス生成(共有) public synchronized BigChar getBigChar(char charname) { BigChar bc = (BigChar)pool.get("" + charname); if (bc == null) { // BigCharのインスタンスを生成 bc = new BigChar(charname); pool.put("" + charname, bc); } return bc; } } 1 import java.util.HashMap; public class BigCharFactory { private HashMap pool = new HashMap(); private static BigCharFactory singleton = new BigCharFactory(); private BigCharFactory() { } // 唯一のインスタンスを得る public static BigCharFactory getInstance() { return singleton; } // BigCharのインスタンス生成(共有) public synchronized BigChar getBigChar(char charname) { BigChar bc = (BigChar)pool.get("" + charname); if (bc == null) { // BigCharのインスタンスを生成 bc = new BigChar(charname); pool.put("" + charname, bc); } return bc; } } public class BigChar { private char charname; // 文字の名前 private String fontdata; public BigChar(char charname) { // コンストラクタ this.charname = charname; try { BufferedReader reader = new BufferedReader( new FileReader("big" + charname + ".txt") ); String line; StringBuffer buf = new StringBuffer(); while ((line = reader.readLine()) != null) { buf.append(line); buf.append("¥n"); } reader.close(); this.fontdata = buf.toString(); } catch (IOException e) { this.fontdata = charname + "?"; } } public void print() { // 大きな文字を表示する System.out.print(fontdata); } } 1 15 プログラムの流れ BigCharFactoryクラス プログラムの流れ BigStringクラス import java.util.HashMap; public class BigCharFactory { private HashMap pool = new HashMap(); private static BigCharFactory singleton = new BigCharFactory(); private BigCharFactory() { } // 唯一のインスタンスを得る public static BigCharFactory getInstance() { return singleton; } // BigCharのインスタンス生成(共有) public synchronized BigChar getBigChar(char charname) { BigChar bc = (BigChar)pool.get("" + charname); if (bc == null) { // BigCharのインスタンスを生成 2 bc = new BigChar(charname); pool.put("" + charname, bc); } return bc; 16 BigCharFactoryクラス public class BigString { // 「大きな文字」の配列 private BigChar[] bigchars; // コンストラクタ public BigString(String string) { bigchars = new BigChar[string.length()]; BigCharFactory factory = BigCharFactory.getInstance(); for (int i = 0; i < bigchars.length; i++) { bigchars[i] = factory.getBigChar(string.charAt(i)); } } // 表示 public void print() { for (int i = 0; i < bigchars.length; i++) { bigchars[i].print(); } } } 1212123 2 BigStringクラス import java.util.HashMap; public class BigCharFactory { private HashMap pool = new HashMap(); private static BigCharFactory singleton = new BigCharFactory(); private BigCharFactory() { } // 唯一のインスタンスを得る public static BigCharFactory getInstance() { return singleton; } // BigCharのインスタンス生成(共有) public synchronized BigChar getBigChar(char charname) { BigChar bc = (BigChar)pool.get("" + charname); if (bc == null) { // BigCharのインスタンスを生成 1 bc = new BigChar(charname); pool.put("" + charname, bc); } return bc; } public class BigString { // 「大きな文字」の配列 private BigChar[] bigchars; // コンストラクタ public BigString(String string) { bigchars = new BigChar[string.length()]; BigCharFactory factory = BigCharFactory.getInstance(); for (int i = 0; i < bigchars.length; i++) { bigchars[i] = factory.getBigChar(string.charAt(i)); } } // 表示 public void print() { for (int i = 0; i < bigchars.length; i++) { bigchars[i].print(); } } } 1212123 1 } } } 17 18 3 2015/6/28 “12123”に対応するBigStringの インスタンスの様子 まとめ • Flyweightは、「インスタンスを共有」 – newの削減 ⇨ メモリの消費量を削減 ⇨ プログラムの実行速度の向上 • 短所 – 共有するインスタンスの変更は、複数箇所に影響 ⇨ 共有させるべきインスタンスとそうでないものを区別することが重要 19 20 4