【デザインパターン】【GoF】【Java】Flyweight パターン

Flyweight パターン

* 生成済みのオブジェクトをできるだけ再利用(共有)し、
 無駄なオブジェクト生成処理(メモリ使用)を防止するパターン

登場人物

Flyweight

 * 多くのオブジェクトを生成され得る可能性のあるクラス

FlyweightFactory

★このクラスがキモ★
 * 「Flyweight」を生成管理する工場
 * 「Flyweight」のオブジェクトが必要な場合は、この工場経由で取得
 * 生成した「Flyweight」オブジェクトをMapなどで貯めて(プール)おく
 * 共有可能なオブジェクトが要求された場合は、プールから返却

Client

 * 利用者

サンプル

Logger.java

* Flyweight
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

public class Logger {
   private String logFilePath;
   private PrintWriter printWriter = null;
   public Logger(String logFilePath) throws UnsupportedEncodingException, FileNotFoundException {
      this.logFilePath = logFilePath;
      this.printWriter = new PrintWriter(
            new OutputStreamWriter(
                  new FileOutputStream(
                        new File(logFilePath)), "UTF-8"));
   }
   @SuppressWarnings("unused")
   private Logger() {
   }
   public String getLogFilePath() {
      return this.logFilePath;
   }
   public void writeLog(String content) {
      this.printWriter.println(content);
      this.printWriter.flush();
   }

   public void close() {
      if (this.printWriter != null) {
         this.printWriter.close();
      }
   }
}

LoggerFactory.java

* FlyweightFactory
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

public class LoggerFactory {
    private Map<String, Logger> loggers = null;
    public LoggerFactory() {
       this.loggers = new HashMap<String, Logger>();
    }

    /** マルチスレッドを考慮し、「Synchronized」修飾子を付け、同期化さる。 
     * @throws FileNotFoundException 
     * @throws UnsupportedEncodingException */
    public synchronized Logger createInstance(String filePath)
          throws UnsupportedEncodingException,
          FileNotFoundException{
       Logger logger = this.loggers.get(filePath);
        if (logger == null){
           logger = new Logger(filePath);
           this.loggers.put(filePath, logger);
        }
        return logger;
    }
    
    public void finalize() {
       for(Logger logger : loggers.values()) {
          logger.close();
       }
    }
}

Main.java

* Client
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;

public class Main {
   public static void main(String[] args) {
      LoggerFactory loggerFactory = new LoggerFactory();
      try {
         Logger logger1 = loggerFactory.createInstance("test1.txt");
         Logger logger2 = loggerFactory.createInstance("test2.txt");
         
         logger1.writeLog("123");
         logger1.writeLog("456");
         
         logger2.writeLog("abc");
         logger2.writeLog("def");
         
         loggerFactory.finalize();
         System.out.println("Check your files");
      } catch (UnsupportedEncodingException e) {
         e.printStackTrace();
      } catch (FileNotFoundException e) {
         e.printStackTrace();
      }
   }
}

勉強した個人的な意見・見解

 * Singletonの応用で、ただMap(C#だとDictionary)を使って、複数オブジェクト持てるってだけじゃ?



あんま関係ないけどサンプル書く時に読み返した記事

ファイルの読み書き

http://blogs.yahoo.co.jp/dk521123/32132680.html

コレクション ~ Map 編~

http://blogs.yahoo.co.jp/dk521123/33002154.html