Menu
CoddyTech

Padrão Factory

Parte da seção Programação orientada a objetos do Journey de GDScript da Coddy. Lição 47 de 65.

O padrão Factory concentra em um só lugar a escolha de qual classe criar. O restante do programa pede à fábrica "um goblin" e recebe um objeto, sem nomear a classe Goblin.

Os produtos compartilham uma classe pai, então o código que os utiliza funciona com qualquer um deles:

# 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"

A fábrica é uma classe com uma static func que transforma um nome em um objeto. Seu tipo de retorno é a classe pai, então ela pode retornar qualquer tipo de inimigo, ou null para um nome que não conhece:

# 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

Nomes como esses geralmente vêm de dados: uma tabela de surgimento, um arquivo de fase, um comando digitado pelo jogador. A fábrica é o único lugar que os associa a classes, então adicionar um Dragon exige um novo arquivo e um novo ramo no match.

Uma fábrica também pode configurar o objeto antes de retorná-lo, para que cada chamador receba um inimigo pronto para usar:

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) retorna um Orc com 300 HP.

challenge icon

Desafio

Médio

Uma tabela de surgimento especifica inimigos e níveis. Enemy (enemy.gd) e sua subclasse Goblin (goblin.gd) já estão escritos; termine o restante:

  • Em orc.gd, o construtor _init(level) passa o nome Orc, 25 * level HP e 4 + level de dano para o construtor da classe pai, como Goblin faz.
  • Em enemy_factory.gd, static func create(kind, level) retorna um Goblin para goblin e um Orc para orc, criados com esse nível. Letras maiúsculas no nome não importam (ORC é um orc). Qualquer outro nome retorna null.

O código fornecido lê quantos surgimentos vêm a seguir, depois uma linha KIND LEVEL para cada surgimento, e exibe cada inimigo ou Unknown enemy: KIND, e então quantos inimigos surgiram. Para goblin 2, Orc 3 e slime 1, a saída é:

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

Seu código deve ficar em enemy_factory.gd e orc.gd. main.gd contém o código fornecido de entrada/saída e não pode ser editado.

Experimente você mesmo

extends Node

func _ready():
	# Código de entrada/saída fornecido: mantenha-o como está
	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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação orientada a objetos

Pratique por conta própria: Compilador de GDScript online