はじめに
本エントリーは某社内で実施するデザインパターン勉強会向けの資料となります。
本エントリーで書籍「Java言語で学ぶデザインパターン入門」をベースに学習を進めますが、サンプルコードはC#に置き換えて解説します。
第1回:Iteratorパターン
第2回:Adapterパターン
第3回:Template Methodパターン
第4回:Factory Methodパターン
第5回:Singletonパターン
第6回:Prototypeパターン
第7回:Builderパターン
第8回:Abstract Factoryパターン
第9回:Bridgeパターン
第10回:Strategyパターン
第11回:Compositeパターン
第12回:Decoratorパターン
第13回:Visitorパターン
第14回:Chain of Responsibilityパターン
第15回:Facadeパターン
第16回:Mediatorパターン
第17回:Observerパターン
第18回:Mementoパターン
第19回:Stateパターン
Flyweightパターンとは
まず、flyweightというのはボクシングで最も体重が軽い階級のことを表しています。すなわちFryweightパターンというのは、オブジェクトを軽くするためのデザインパターンです。ここでいう重さはメモリの使用量を表しており、たくさんのメモリを使うオブジェクトを「重い」、少ししかメモリを使わないオブジェクトを「軽い」と表しています。
新しいクラスのインスタンスを作ると、そのインスタンスを保持するために、メモリが確保されます。そのクラスのインスタンスを沢山作ると、メモリの使用量が大きくなってしまいます。
すなわちFryweightパターンは、等価なインスタンスを別々の箇所で使用する際、一つのインスタンスを再利用することによってプログラムを省リソース化することを目的としているデザインパターンになります。
クラス図
各クラスの役割
名前 | 役割 |
---|---|
BigChar | 「大きな文字」を表すクラス |
BigCharFactory | BigCharのインスタンスを共有しながら生成するクラス |
BigString | BigCharを集めて作った「大きな文字列」を表すクラス |
Program | 動作テスト用のクラス |
BigCharクラス
大きな文字を表現する(重いインスタンスを作る)クラス。
ファイルから大きな文字のテキストを読み込んでメモリ上に蓄え、printメソッドでそれを表示する。
class BigChar
{
//文字の名前
private char charname;
//大きな文字を表現する文字列
private String fontdata;
public BigChar(char charname)
{
this.charname = charname;
String pass = String.Format("..\\..\\..\\Fryweightpt\\Fryweightpt\\Fryweightpt\\inputTxt\\big{0}.txt", this.charname);
try
{
System.IO.StreamReader reader = (
new System.IO.StreamReader(pass, System.Text.Encoding.Default)
);
String line;
while ((line = reader.ReadLine()) != null)
{
fontdata += line + "\n";
}
}
catch (IOException e)
{
this.fontdata = charname + "?";
}
}
//大きい文字を表示
public void print()
{
Console.Write(fontdata);
}
}
BigCharFactoryクラス
BigCharのインスタンスを生成するクラス。
同じ文字に対応するBigCharのインスタンスが既に作ってあった場合は、それを利用し、新しいインスタンスは作らない。また、factoryクラスは複数生成する必要がないため、Singletonパターンで実装されています。
class BigCharFactory
{
//既に作ったBigCharのインスタンスを管理
private Hashtable pool = new Hashtable();
//Singletonパターン
private static BigCharFactory bigCharFactory = new BigCharFactory();
private BigCharFactory()
{
}
public static BigCharFactory getInstance()
{
return bigCharFactory;
}
//BigCharのインスタンス作成
public BigChar getBigChar(char charname)
{
BigChar bigChar = (BigChar)pool["" + charname];
if (bigChar == null)
{
bigChar = new BigChar(charname);
pool.Add("" + charname, bigChar);
}
return bigChar;
}
}
BigStringクラス
BigCharを集めた大きな文字列を表すクラス。
BigCharのインスタンスを保持する。
class BigString
{
//「大きな文字」の配列
private BigChar[] bigchars;
public BigString(String str)
{
bigchars = new BigChar[str.Length];
BigCharFactory bigCharFactory = BigCharFactory.getInstance();
for(int i=0; i< bigchars.Length; i++)
{
bigchars[i] = bigCharFactory.getBigChar(str[i]);
}
}
//表示
public void print()
{
for(int i=0; i < bigchars.Length; i++)
{
bigchars[i].print();
}
}
}
Programクラス
動作テスト用のクラス。
引数で与えられた文字列を元に、BigStringのインスタンスを作り、それを表示する。
class Program
{
static void Main(string[] args)
{
if(args.Length == 0)
{
Console.WriteLine("please enter a number !");
Console.ReadLine();
System.Environment.Exit(0);
}
BigString bigString = new BigString(args[0]);
bigString.print();
Console.ReadLine();
}
}
txtファイル
大きな文字を構成しているデータ。
文字の前にbigという文字列を付けたファイル名。
例 : big1.txt
--------------
-----##-------
--#####-------
-----##-------
-----##-------
-----##-------
-----##-------
-----##-------
--########----
--------------
#プログラム実行結果
実行時引数を 0121 とした場合。
----#####-----
--##-----##---
--##-----##---
--##-----##---
--##-----##---
--##-----##---
----#####-----
--------------
--------------
-----##-------
--#####-------
-----##-------
-----##-------
-----##-------
-----##-------
-----##-------
--########----
--------------
--------------
----######----
--##----###---
--------###---
-----###------
---##---------
-##-----------
-##########---
--------------
--------------
-----##-------
--#####-------
-----##-------
-----##-------
-----##-------
-----##-------
-----##-------
--########----
--------------
#考察
・重複したインスタンスを生成することがなくなるため、インスタンスの管理をfactoryに任せておけば、既に生成している、いないの管理をインスタンスを使う側でする必要がなくなる。
・インスタンスを共有しているので、一つのインスタンスを変更するだけでそのインスタンスを使っている複数箇所に同時に変更が反映されてしまう。
→複数箇所に共有させるべき情報だけ、Fryweight役に持たせるべきである。