Flyweightパターンは、GoF(Gang of Four)の23のデザインパターンの一つで、システム内で大量のオブジェクトを効率よく扱い、メモリ使用量を抑えるために設計されています。
本記事では、Flyweightパターンの概要から具体的な使い方、Javaによる実装サンプルまで詳しく解説します。
デザインパターンに興味がある方や、オブジェクト指向プログラミングの効率化に取り組みたい方にとって、有益な内容となっています。
Flyweightとは
Flyweightパターンは、オブジェクトのインスタンス生成に伴うメモリコストを削減するために利用されるデザインパターンです。
多くのオブジェクトを共有してメモリ使用量を最小化し、冗長なオブジェクトを作成することなく必要な機能を提供することが主な目的です。
このパターンは、システム内で大量のオブジェクトが生成され、それらが同じデータを保持する場合に特に有効です。
Flyweightの使い方
Flyweightパターンを利用する場面では、まずオブジェクトの冗長性を特定し、その冗長な部分を共有することで効率化を図ります。
典型的な例としては、文字や画像など、同じデータを複数回使用する場合です。これらをFlyweightとして一度だけ生成し、必要な箇所で共有します。
使用の手順
Flyweightの利点と欠点
利点: メモリ消費を大幅に削減できることが挙げられます。
欠点: 複雑な管理が必要になり、コードの可読性が下がる場合があります。
また、Flyweightオブジェクトと個別データの区別を正確に行う必要があります。
Flyweight実装サンプル
次に、Flyweightパターンの実装サンプルをJavaで紹介します。例として、複数の同じ形状のオブジェクトを生成し、それらを効率的にメモリ内で共有する方法を示します。
Java実装例
以下は、Flyweightパターンを利用して図形(Shape)を扱う簡単な例です。FlyweightとしてのShapeオブジェクトは共有され、色などの属性だけが異なるように設計されています。
/* Flyweight インターフェース */
interface Shape {
void draw();
}
/* ConcreteFlyweight クラス */
class Circle implements Shape {
private String color;
private int x;
private int y;
private int radius;
public Circle(String color){
this.color = color;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setRadius(int radius) {
this.radius = radius;
}
@Override
public void draw() {
System.out.println("Circle: Draw() [Color : " + color + ", x : " + x + ", y :" + y + ", radius :" + radius);
}
}
/* FlyweightFactory クラス */
class ShapeFactory {
private static final HashMap<String, Shape> circleMap = new HashMap<>();
public static Shape getCircle(String color) {
Circle circle = (Circle)circleMap.get(color);
if(circle == null) {
circle = new Circle(color);
circleMap.put(color, circle);
System.out.println("Creating circle of color : " + color);
}
return circle;
}
}
/* クライアントコード */
public class FlyweightPatternDemo {
private static final String colors[] = { "Red", "Green", "Blue", "White", "Black" };
public static void main(String[] args) {
for(int i=0; i < 20; ++i) {
Circle circle = (Circle)ShapeFactory.getCircle(getRandomColor());
circle.setX(getRandomX());
circle.setY(getRandomY());
circle.setRadius(100);
circle.draw();
}
}
private static String getRandomColor() {
return colors[(int)(Math.random()*colors.length)];
}
private static int getRandomX() {
return (int)(Math.random()*100 );
}
private static int getRandomY() {
return (int)(Math.random()*100);
}
}
この実装では、同じ色のCircleオブジェクトが共有され、効率的に再利用されています。
まとめ
Flyweightパターンは、大量のオブジェクトが同じデータを共有している状況で、メモリの最適化に有効です。
本記事では、Flyweightパターンの基本的な概念、使用方法、およびJavaでの実装例を紹介しました。
Flyweightパターンを使用することで、リソースの無駄を削減し、パフォーマンスを向上させることが可能です。
ただし、パターンの適用には管理の難しさも伴うため、適切な場面で使用することが重要です。