デザインパターン入門
CoddyのGDScriptジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 45/65。
デザインパターンとは、プログラムを作るたびに繰り返し現れる問題に対して、クラスをどのように構成するかを示す、よく知られた名前付きの方法です。ライブラリでも、そのままコピーするコードでもありません。どのオブジェクトが存在し、それぞれが何を担当し、どのように連携するのかを説明するものです。自分のゲームに合わせて、自分でコードを書きます。
パターンは、開発者同士で共通の用語を使えるようにもします。「敵はファクトリーから生成される」や「体力バーはプレイヤーを監視する」と言えば、ファイルを開く前にコードの構成をチームメイトに伝えられます。
パターンで解決できる問題を紹介します。レベルを開始するには3つのオブジェクトとやり取りする必要があり、レベルを開始するすべてのスクリプトで次の行が繰り返されます。
var music := MusicPlayer.new()
var level_map := LevelMap.new()
var hud := Hud.new()
music.play("forest.ogg")
level_map.load_map(1)
hud.show_hearts(3)Facadeパターンでは、それらのオブジェクトの前に1つのクラスを置き、シンプルなメソッドを1つ用意します。
# game_facade.gd
class_name GameFacade
extends RefCounted
var music := MusicPlayer.new()
var level_map := LevelMap.new()
var hud := Hud.new()
func start_level(number: int) -> void:
music.play("forest.ogg")
level_map.load_map(number)
hud.show_hearts(3)# main.gd
var game := GameFacade.new()
game.start_level(1)Music: playing forest.ogg
Map: level 1 loaded
HUD: hearts 3プログラムの残りの部分ではstart_level()を呼び出し、レベルの開始方法を変更するときは、1つのファイルを編集します。
パターンは、解決する問題ごとに分類されます。
- 生成パターンはオブジェクトの生成方法を制御します:Singleton、Factory。
- 構造パターンはオブジェクトを組み合わせてより大きな構造を作ります:Facade、Adapter、Decorator、Composite。
- 振る舞いパターンはオブジェクト同士の連携方法を整理します:Observer、Strategy、Command、Template Method、State。
この章と次の章では、これらのパターンを扱います。それぞれ、独立したファイル内のクラス、継承、ポリモーフィズム、コンポジション、シグナルなど、すでに学んだことをもとに構成されています。
チャレンジ
簡単ゲームは、すでに実装されている3つのオブジェクトを通じてレベルを開始および終了します。MusicPlayer(music_player.gd)、LevelMap(level_map.gd)、Hud(hud.gd)です。これらの前面にファサード GameFacade を作成してください。
- メンバー変数として、
MusicPlayer、LevelMap、Hudをそれぞれ1つずつ作成します。 start_level(number, hearts)は、トラックlevel_N.ogg(Nはレベル番号)を再生します。ただし、番号が5の倍数の場合はboss.oggを再生します。その後、そのレベルのマップを読み込み、ハートを表示します。quit_level()はHUDを非表示にしてから、音楽を停止します。
提供されたコードは、後続するコマンドの数を読み込んだ後、1行につき1つのコマンドを読み込みます。コマンドは start NUMBER HEARTS または quit です。start 5 2 と quit の出力は次のとおりです。
Music: playing boss.ogg
Map: level 5 loaded
HUD: hearts 2
HUD: hidden
Music: stoppedコードは game_facade.gd に記述してください。main.gd には提供された入出力コードがあり、編集できません。
自分で試してみよう
extends Node
func _ready():
# 提供された入出力コード: そのままにしてください
var game := GameFacade.new()
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
if parts[0] == "start":
game.start_level(int(parts[1]), int(parts[2]))
elif parts[0] == "quit":
game.quit_level()
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: GDScriptオンラインコンパイラ