Menu
CoddyTech

Patrón Adapter

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

El patrón Adapter permite que un objeto funcione con código que espera métodos diferentes. El adaptador envuelve el objeto y convierte cada llamada esperada en una llamada que el objeto entiende.

Una clase antigua de un proyecto anterior almacena la salud como dos números:

# old_monster.gd
class_name OldMonster
extends RefCounted

var life := 30
var max_life := 120

Tu HUD muestra cualquier cosa que tenga get_label() y get_hp_percent(). Un Knight ya tiene ambos (devuelve "Knight" y 80), pero OldMonster no tiene ninguno:

# health_display.gd
class_name HealthDisplay
extends RefCounted

func show_health(target) -> void:
	print(target.get_label(), ": ", target.get_hp_percent(), "%")

El adaptador contiene un OldMonster y proporciona los dos métodos que llama la pantalla:

# monster_adapter.gd
class_name MonsterAdapter
extends RefCounted

var monster: OldMonster

func _init(wrapped: OldMonster) -> void:
	monster = wrapped

func get_label() -> String:
	return "Monster"

func get_hp_percent() -> int:
	return monster.life * 100 / monster.max_life
# main.gd
var display := HealthDisplay.new()
display.show_health(Knight.new())
display.show_health(MonsterAdapter.new(OldMonster.new()))
Knight: 80%
Monster: 25%

Ni OldMonster ni HealthDisplay cambiaron. Eso importa cuando no puedes o no debes editar una clase: proviene de un complemento, pertenece a otro equipo o muchos scripts dependen de sus nombres.

El adaptador reenvía cada llamada y convierte los datos sobre la marcha: aquí, dos números en un porcentaje. Multiplica antes de dividir: con enteros, 30 / 120 * 100 es 0, mientras que 30 * 100 / 120 es 25.

challenge icon

Desafío

Fácil

Una estación meteorológica muestra sensores que tienen get_sensor_name() y get_celsius(), como ModernSensor (modern_sensor.gd). La estación está en weather_board.gd. Los termómetros antiguos (legacy_thermometer.gd) solo ofrecen read_fahrenheit() y get_code(). Escribe el adaptador ThermometerAdapter:

  • El constructor guarda el LegacyThermometer envuelto.
  • get_sensor_name() devuelve Thermometer, un espacio y el código del termómetro, como Thermometer TH-4.
  • get_celsius() devuelve la temperatura en Celsius: (fahrenheit - 32) * 5 / 9, como float.

No cambies las demás clases. El código proporcionado lee cuántos sensores vienen a continuación y luego uno por línea: legacy ID FAHRENHEIT o modern NAME CELSIUS. Envuelve cada termómetro antiguo en tu adaptador y muestra todos los sensores. Para legacy 4 98.6 y modern Garden 21.5, la salida es:

Thermometer TH-4: 37.0 C
Garden: 21.5 C
Warmest: Thermometer TH-4

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

Pruébalo tú mismo

extends Node

func _ready():
	# Código de entrada/salida proporcionado: mantenlo tal como está
	var board := WeatherBoard.new()
	var count := int(OS.read_string_from_stdin())
	for i in count:
		var parts := OS.read_string_from_stdin().split(" ")
		if parts[0] == "legacy":
			var old := LegacyThermometer.new(int(parts[1]), float(parts[2]))
			board.add_sensor(ThermometerAdapter.new(old))
		else:
			board.add_sensor(ModernSensor.new(parts[1], float(parts[2])))
	board.show_all()
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