前回、大量の弾オブジェクトを生成すると、メモリ使用量が爆発することがわかりました。でも、よく考えると「見た目」は共有できるのに「位置」は弾ごとに違う…。
この気づきを設計に活かしてみましょう!

前回の振り返り
前回発見した問題を整理します:
- 100発の「赤い丸弾」を生成した
- すべての弾が同じ
shape、color、sizeを持っている - でも、1発あたり約600バイトのメモリを消費
- 見た目は共有できるはずなのに、全部別々に持っている
弾の「種類」と「個体」を分離する
ここで発想を変えてみましょう。
弾を「種類(BulletType)」と「個体(弾そのもの)」に分けて考えます:
| 分類 | 内容 | 弾ごとに異なる? |
|---|---|---|
| 種類(BulletType) | 形状、色、サイズ | いいえ!同じ種類なら同じ |
| 個体(位置情報) | X座標、Y座標、速度 | はい!弾ごとに違う |
「赤い丸弾」という種類は1つだけ作って、それを100発の弾で共有すればいいのです!
BulletTypeクラスを作る
まず、弾の「種類」を表すクラスを作りましょう:
| |
実行結果:
| |
これで、弾の「種類」を3つ定義できました。
位置情報を分離する
次に、「個体」としての位置情報を管理する方法を考えます。
前回は Bullet クラスに全部入れていましたが、今回は位置情報だけをハッシュで持つようにしてみましょう:
| |
実行結果:
| |
前回との比較
| 項目 | 前回(分離なし) | 今回(分離あり) |
|---|---|---|
| 弾100発のメモリ | 60.8KB | 25.2KB |
| BulletTypeオブジェクト数 | なし(弾ごとに属性を持つ) | 3つ(共有) |
| メモリ削減率 | - | 約60%削減! |
見た目の情報を共有するだけで、メモリ使用量が大幅に減りました!
「内部状態」と「外部状態」
ここで、専門用語を紹介します:
| 用語 | 意味 | 本シリーズでの例 |
|---|---|---|
| 内部状態(Intrinsic State) | オブジェクト間で共有できる状態 | 形状、色、サイズ(BulletType) |
| 外部状態(Extrinsic State) | オブジェクトごとに異なる状態 | 位置、速度(弾ごとの情報) |
「内部状態」を持つオブジェクトを共有し、「外部状態」は使用時に渡す。これがメモリ効率化の基本的な考え方です。
renderメソッドに位置を渡す
注目してほしいのは、render メソッドの呼び出し方です:
| |
BulletType オブジェクトは、自分の位置を知りません。描画するときに「外部から位置を受け取る」のです。
これが「外部状態を渡す操作」です。
次回予告
分離の考え方はわかりました。でも、毎回 BulletType->new(...) を呼び出すのは面倒ですし、同じ種類の弾を何度も new してしまう危険もあります。
次回は、BulletFactory というクラスを作って、同じ種類の弾は確実に同じオブジェクトを返すようにします。
今回のまとめ
- 弾の「種類」と「位置」を分けて考える
- 内部状態(形状、色、サイズ):共有可能 →
BulletTypeクラス - 外部状態(位置、速度):弾ごとに異なる → 使用時に渡す
- この分離により、メモリ使用量を約60%削減できた
- 次回:
BulletFactoryで弾の種類を管理する
今回の完成コード
| |
