Menu
CoddyTech

テンプレートメソッドパターン

CoddyのGDScriptジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 53/65。

Template Method パターンは、親クラスでアルゴリズムの手順の順序を固定し、各サブクラスがその手順の一部を埋められるようにします。手順を実行する親クラスのメソッドがテンプレートメソッドです。

# level.gd
@abstract
class_name Level
extends RefCounted

func play() -> void:
	print("Loading ", get_level_name())
	spawn_enemies()
	print("Level complete!")

@abstract func get_level_name() -> String
@abstract func spawn_enemies() -> void

play()はテンプレートです。すべてのレベルはこの順序で読み込まれ、敵を出現させ、完了します。異なる手順は抽象的なので、すべてのサブクラスで実装する必要があります。

# forest_level.gd
class_name ForestLevel
extends Level

func get_level_name() -> String:
	return "Forest"

func spawn_enemies() -> void:
	print("3 wolves appear")

CaveLevel も同じように記述し、名前は "Cave"、5 bats appear とします。

# main.gd
var levels: Array[Level] = [ForestLevel.new(), CaveLevel.new()]
for level in levels:
	level.play()
Loading Forest
3 wolves appear
Level complete!
Loading Cave
5 bats appear
Level complete!

ステップには、親クラスでデフォルトの実装を定義し、サブクラスでオーバーライドできるものもあります。このようなオプションのステップはフックと呼ばれます。

# level.gd
func play() -> void:
	print("Loading ", get_level_name())
	spawn_enemies()
	if has_boss():
		print("The boss arrives")
	print("Level complete!")

func has_boss() -> bool:
	return false

has_boss() をオーバーライドして true を返すレベルだけが、ボスの行を表示します。サブクラスは手順を記述し、親クラスがそれらを実行するタイミングを決定するため、サブクラスでは play() を変更せず、すべてのレベルが同じ順序に従います。

challenge icon

チャレンジ

中級

ゲームは同じ手順でスコアを2つの形式で出力します。行は、"name"と"score"を持つ辞書です。

  • exporter.gdでは、テンプレートメソッドexport_rows(rows)を記述します。まずheader()を出力し、次に各行についてformat_row(row)を出力し、その後footer(rows)を出力します。ヘッダーまたはフッターが空文字列の場合は出力しません。フックのheader()とfooter()はデフォルトで""を返し、format_row()は抽象メソッドです。
  • CsvExporter:ヘッダーはname,scoreで、行はAda,12です。フッターはありません。
  • ListExporter:ヘッダーはなく、行は* Ada scored 12です。フッターは行数を含むPlayers: Nです。

用意されているコードは、形式(csvまたはlist)、続く行数、そして1行につき1つのNAME SCORE行を読み取ります。Ada 12とBo 7を指定したlistの場合、出力は次のとおりです。

* Ada scored 12
* Bo scored 7
Players: 2

コードはexporter.gd、csv_exporter.gd、list_exporter.gdに記述します。main.gdには用意されている入出力コードが含まれており、編集できません。

自分で試してみよう

extends Node

func _ready():
	# 提供された入出力コード: そのままにしてください
	var style := OS.read_string_from_stdin()
	var rows: Array = []
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		rows.append({"name": parts[0], "score": int(parts[1])})
	var exporter: Exporter = CsvExporter.new()
	if style == "list":
		exporter = ListExporter.new()
	exporter.export_rows(rows)
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: GDScriptオンラインコンパイラ