Flyweightパターンとは|GoFデザインパターンの解説

デザインパターンとは IT技術
IT技術

Flyweightパターンは、GoF(Gang of Four)の23のデザインパターンの一つで、システム内で大量のオブジェクトを効率よく扱い、メモリ使用量を抑えるために設計されています。

本記事では、Flyweightパターンの概要から具体的な使い方、Javaによる実装サンプルまで詳しく解説します。

デザインパターンに興味がある方や、オブジェクト指向プログラミングの効率化に取り組みたい方にとって、有益な内容となっています。

Flyweightとは

Flyweightパターンは、オブジェクトのインスタンス生成に伴うメモリコストを削減するために利用されるデザインパターンです。

多くのオブジェクトを共有してメモリ使用量を最小化し、冗長なオブジェクトを作成することなく必要な機能を提供することが主な目的です。

このパターンは、システム内で大量のオブジェクトが生成され、それらが同じデータを保持する場合に特に有効です。

Flyweightの使い方

Flyweightパターンを利用する場面では、まずオブジェクトの冗長性を特定し、その冗長な部分を共有することで効率化を図ります。

典型的な例としては、文字や画像など、同じデータを複数回使用する場合です。これらをFlyweightとして一度だけ生成し、必要な箇所で共有します。

使用の手順

手順
Flyweightの使用手順
  1. オブジェクトを共有する部分(不変部分)と個別に扱う部分(可変部分)に分けます。
  2. 共有する部分をFlyweightオブジェクトとして扱い、ファクトリパターンを使って管理します。
  3. 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パターンを使用することで、リソースの無駄を削減し、パフォーマンスを向上させることが可能です。

ただし、パターンの適用には管理の難しさも伴うため、適切な場面で使用することが重要です。

タイトルとURLをコピーしました