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での実装例を示しましたので、ぜひ自分のプロジェクトに適用してみてください。