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

記事内に広告が含まれています。

Flyweightパターンは、オブジェクトのメモリ使用量を抑えるためのデザインパターンです。

同じようなオブジェクトが大量に作成される場合、それらの共通部分を共有し、必要な部分のみを個別に管理することで、メモリの無駄遣いを防ぐことができます。

本記事では、Flyweightパターンの概要、使い方、Java、C++、C#、VB.NETでの実装例を紹介します。

Flyweightパターンとは

Flyweightパターンは、同一の状態を持つオブジェクトが複数生成される場面で、共通するデータを共有することでメモリの節約を図るデザインパターンです。

特に、大量のオブジェクトが必要なアプリケーションやゲームなどにおいて、オブジェクトのメモリ使用量を効率的に抑えることができます。

Flyweightパターンの概要

Flyweightパターンは、オブジェクトの共有を行うことで、冗長なメモリ使用を防ぎます。

このパターンでは、オブジェクトの不変な部分(インストリック状態)と変化する部分(エクストリック状態)を分けて考え、不変な部分を共有する設計が取られます。

Flyweightパターンの使い方

Flyweightパターンの使い方として、以下のステップがあります。

共通部分の分離

オブジェクトの共通部分と可変部分を明確に分離します。

共通部分はFlyweightオブジェクトとして再利用します。

Flyweightファクトリーの作成

Flyweightオブジェクトを生成するファクトリクラスを作成します。

このクラスは、すでに存在するFlyweightオブジェクトを管理し、必要に応じて新しいオブジェクトを作成します。

3. クライアントによる管理

クライアントは、Flyweightファクトリーを通じてオブジェクトを取得し、個別の状態を管理します。

Flyweightパターン実装サンプル

以下に、FlyweightパターンをJava、C++、C#、VB.NETで実装したサンプルコードを示します。

Javaによる実装


interface Flyweight {
    void operation(String extrinsicState);
}

class ConcreteFlyweight implements Flyweight {
    private String intrinsicState;
    public ConcreteFlyweight(String intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    @Override
    public void operation(String extrinsicState) {
        System.out.println("Intrinsic State: " + intrinsicState + ", Extrinsic State: " + extrinsicState);
    }
}

class FlyweightFactory {
    private Map flyweightPool = new HashMap<>();
    public Flyweight getFlyweight(String key) {
        if (!flyweightPool.containsKey(key)) {
            flyweightPool.put(key, new ConcreteFlyweight(key));
        }
        return flyweightPool.get(key);
    }
}

public class FlyweightPatternDemo {
    public static void main(String[] args) {
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight fw1 = factory.getFlyweight("A");
        Flyweight fw2 = factory.getFlyweight("B");
        fw1.operation("X");
        fw2.operation("Y");
    }
}

C++による実装


#include 
#include 

class Flyweight {
    public:
        virtual void operation(const std::string& extrinsicState) = 0;
    };

    class ConcreteFlyweight : public Flyweight {
        private:
            std::string intrinsicState;
        public:
            ConcreteFlyweight(const std::string& state) : intrinsicState(state) {}
            void operation(const std::string& extrinsicState) override {
                std::cout << "Intrinsic State: " << intrinsicState << ", Extrinsic State: " << extrinsicState << std::endl;
            }
        };

    class FlyweightFactory {
        private:
            std::unordered_map flyweightPool;
        public:
            Flyweight* getFlyweight(const std::string& key) {
                if (flyweightPool.find(key) == flyweightPool.end()) {
                    flyweightPool[key] = new ConcreteFlyweight(key);
                }
                return flyweightPool[key];
            }
        };

    int main() {
        FlyweightFactory factory;
        Flyweight* fw1 = factory.getFlyweight("A");
        Flyweight* fw2 = factory.getFlyweight("B");

        fw1->operation("X");
        fw2->operation("Y");
       return 0;
}

C#による実装


using System;
using System.Collections.Generic;

interface Flyweight {
    void Operation(string extrinsicState);
}

class ConcreteFlyweight : Flyweight {
    private string intrinsicState;
    public ConcreteFlyweight(string intrinsicState) {
        this.intrinsicState = intrinsicState;
    }

    public void Operation(string extrinsicState) {
        Console.WriteLine("Intrinsic State: " + intrinsicState + ", Extrinsic State: " + extrinsicState);
    }
}

class FlyweightFactory {
    private Dictionary flyweightPool = new Dictionary();

    public Flyweight GetFlyweight(string key) {
        if (!flyweightPool.ContainsKey(key)) {
            flyweightPool[key] = new ConcreteFlyweight(key);
        }
        return flyweightPool[key];
    }
}

class Program {
    static void Main(string[] args) {
        FlyweightFactory factory = new FlyweightFactory();

        Flyweight fw1 = factory.GetFlyweight("A");
        Flyweight fw2 = factory.GetFlyweight("B");

        fw1.Operation("X");
        fw2.Operation("Y");
    }
}

VB.NETによる実装


Interface Flyweight
    Sub Operation(ByVal extrinsicState As String)
End Interface

Class ConcreteFlyweight
    Implements Flyweight
    Private intrinsicState As String

    Public Sub New(ByVal intrinsicState As String)
        Me.intrinsicState = intrinsicState
    End Sub

    Public Sub Operation(ByVal extrinsicState As String) Implements Flyweight.Operation
        Console.WriteLine("Intrinsic State: " & intrinsicState & ", Extrinsic State: " & extrinsicState)
    End Sub
End Class

Class FlyweightFactory
    Private flyweightPool As New Dictionary(Of String, Flyweight)

    Public Function GetFlyweight(ByVal key As String) As Flyweight
        If Not flyweightPool.ContainsKey(key) Then
            flyweightPool(key) = New ConcreteFlyweight(key)
        End If
        Return flyweightPool(key)
    End Function
End Class

Module Program
    Sub Main()
        Dim factory As New FlyweightFactory()

        Dim fw1 As Flyweight = factory.GetFlyweight("A")
        Dim fw2 As Flyweight = factory.GetFlyweight("B")

        fw1.Operation("X")
        fw2.Operation("Y")
    End Sub
End Module

まとめ

Flyweightパターンは、オブジェクトのメモリ使用を最適化するために使用される有効なデザインパターンです。

特に、大量の同一オブジェクトが生成される場面で効果を発揮します。

Flyweightパターンを使うことで、システムのパフォーマンス向上やメモリ節約が期待できるため、適切な場面での活用が重要です。

この記事では、Java、C++、C#、VB.NETでの実装例を示しましたので、ぜひ自分のプロジェクトに適用してみてください。

オブジェクト指向プログラミングにおけるGoFの23のデザインパターン
デザインパターンは、ソフトウェア設計の問題を効果的に解決するための再利用可能な解決策です。本記事では、GoF(Gang ...
【PR】
オブジェクト指向学習におすすめの本
オブジェクト指向
スポンサーリンク
タイトルとURLをコピーしました