Menu
CoddyTech

Patrón Factory

Parte de la sección Programación orientada a objetos del Journey de GDScript de Coddy. Lección 47 de 65.

El patrón Factory centraliza la elección de qué clase crear. El resto del programa le pide a la fábrica «un goblin» y recibe un objeto, sin nombrar la clase Goblin.

Los productos comparten una clase padre, así que el código que los usa funciona con cualquiera de ellos:

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

La fábrica es una clase con una static func que convierte un nombre en un objeto. Su tipo de retorno es la clase padre, por lo que puede devolver cualquier tipo de enemigo, o null para un nombre que no reconoce:

# 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

Nombres como estos suelen provenir de datos: una tabla de aparición, un archivo de nivel, un comando que escribió el jugador. La fábrica es el único lugar que los asigna a clases, así que añadir un Dragon requiere un archivo nuevo y una rama nueva en match.

Una fábrica también puede preparar el objeto antes de devolverlo, para que cada persona que lo solicite obtenga un enemigo listo 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) devuelve un Orc con 300 HP.

challenge icon

Desafío

Intermedio

Una tabla de aparición indica enemigos y niveles. Ya están escritos Enemy (enemy.gd) y su subclase Goblin (goblin.gd); termina el resto:

  • En orc.gd, el constructor _init(level) pasa el nombre Orc, 25 * level HP y 4 + level de daño al constructor de la clase padre, igual que hace Goblin.
  • En enemy_factory.gd, static func create(kind, level) devuelve un Goblin para goblin y un Orc para orc, creado con ese nivel. No importa que las letras del nombre estén en mayúsculas (ORC es un orco). Cualquier otro nombre devuelve null.

El código proporcionado lee cuántas apariciones siguen y, después, una línea KIND LEVEL por aparición, e imprime cada enemigo o Unknown enemy: KIND y, después, cuántos enemigos aparecieron. Para goblin 2, Orc 3 y slime 1, la salida es:

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

Tu código va en enemy_factory.gd y orc.gd. main.gd contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

extends Node

func _ready():
	# Código de entrada/salida proporcionado: déjalo tal 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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de GDScript online