Menu
CoddyTech

ファクトリーパターン

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

ファクトリーパターンでは、どのクラスを作成するかの選択を一か所に集約します。プログラムのほかの部分はファクトリに「ゴブリンを1体」と要求してオブジェクトを受け取るため、クラス名 Goblin を指定する必要はありません。

生成物は親クラスを共有しているため、それらを使用するコードはどの生成物でも動作します。

# enemy.gd
class_name Enemy
extends RefCounted

var hp := 10

func attack() -> String:
	return "The enemy waits"
# goblin.gd
class_name Goblin
extends Enemy

func attack() -> String:
	return "The goblin stabs"
# orc.gd
class_name Orc
extends Enemy

func attack() -> String:
	return "The orc smashes"

ファクトリーは、名前をオブジェクトに変換する static func を持つクラスです。戻り値の型は親クラスなので、あらゆる種類の敵を返すことができ、知らない名前に対しては null を返します:

# enemy_factory.gd
class_name EnemyFactory
extends RefCounted

static func create(kind: String) -> Enemy:
	match kind:
		"goblin":
			return Goblin.new()
		"orc":
			return Orc.new()
	return null
# main.gd
for kind in ["orc", "goblin", "slime"]:
	var enemy := EnemyFactory.create(kind)
	if enemy == null:
		print("Unknown enemy: ", kind)
	else:
		print(enemy.attack())
The orc smashes
The goblin stabs
Unknown enemy: slime

このような名前は、通常データから取得されます。スポーンテーブル、レベルファイル、プレイヤーが入力したコマンドなどです。クラスへの対応付けを行うのはファクトリーだけなので、Dragonを追加するには、新しいファイルを1つ作成し、matchに新しい分岐を1つ追加するだけです。

ファクトリーはオブジェクトを返す前に設定することもできるため、呼び出し元は誰でもすぐに使える敵を受け取れます。

static func create_boss(kind: String, level: int) -> Enemy:
	var boss := create(kind)
	if boss != null:
		boss.hp = 100 * level
	return boss

EnemyFactory.create_boss("orc", 3)はHPが300のOrcを返します。

challenge icon

チャレンジ

中級

スポーンテーブルには敵とレベルが記載されています。Enemy(enemy.gd)とそのサブクラスのGoblin(goblin.gd)はすでに記述されています。残りを完成させましょう。

  • orc.gdでは、コンストラクターの_init(level)から親コンストラクターに名前Orc、HPの25 * level、ダメージの4 + levelを渡します。Goblinと同じ方法です。
  • enemy_factory.gdでは、static func create(kind, level)が、goblinにはGoblinを、orcにはOrcを返すようにします。どちらも指定されたレベルで作成します。名前の大文字・小文字は区別されません(ORCはorcです)。それ以外の名前にはnullを返します。

用意されているコードは、後に続くスポーン数を読み取り、各スポーンについてKIND LEVELの行を1行ずつ読み込み、各敵またはUnknown enemy: KINDを出力した後、スポーンした敵の数を出力します。goblin 2、Orc 3、slime 1の場合、出力は次のとおりです。

Goblin: 20 HP, 4 damage
Orc: 75 HP, 7 damage
Unknown enemy: slime
Spawned: 2

コードはenemy_factory.gdとorc.gdに記述します。main.gdには用意されている入出力コードがあり、編集できません。

自分で試してみよう

extends Node

func _ready():
	# 用意された入出力コード:そのままにしてください
	var spawned := 0
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		var enemy := EnemyFactory.create(parts[0], int(parts[1]))
		if enemy == null:
			print("Unknown enemy: ", parts[0])
		else:
			spawned += 1
			print(enemy.describe())
	print("Spawned: ", spawned)
quiz icon腕試し

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

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

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