Menu
CoddyTech

Padrão Adapter

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

O padrão Adapter permite que um objeto funcione com código que espera métodos diferentes. O adaptador envolve o objeto e transforma cada chamada esperada em uma chamada que o objeto entende.

Uma classe antiga de um projeto anterior armazena a vida como dois números:

# old_monster.gd
class_name OldMonster
extends RefCounted

var life := 30
var max_life := 120

Seu HUD exibe qualquer coisa que tenha get_label() e get_hp_percent(). Um Knight já tem ambos (ele retorna "Knight" e 80), mas OldMonster não tem nenhum dos dois:

# health_display.gd
class_name HealthDisplay
extends RefCounted

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

O adaptador contém um OldMonster e fornece os dois métodos que o visor chama:

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

Nem OldMonster nem HealthDisplay mudou. Isso é importante quando você não pode ou não deve editar uma classe: ela vem de um plugin, pertence a outra equipe ou muitos scripts dependem dos nomes dela.

O adaptador encaminha cada chamada e converte os dados durante o processo; aqui, dois números em uma porcentagem. Multiplique antes de dividir: com inteiros, 30 / 120 * 100 é 0, enquanto 30 * 100 / 120 é 25.

challenge icon

Desafio

Fácil

Um painel meteorológico exibe sensores que têm get_sensor_name() e get_celsius(), como ModernSensor (modern_sensor.gd). O painel está em weather_board.gd. Termômetros antigos (legacy_thermometer.gd) oferecem apenas read_fahrenheit() e get_code(). Escreva o adaptador ThermometerAdapter:

  • O construtor armazena o LegacyThermometer encapsulado.
  • get_sensor_name() retorna Thermometer, um espaço e o código do termômetro, como Thermometer TH-4.
  • get_celsius() retorna a temperatura em Celsius: (fahrenheit - 32) * 5 / 9, como um float.

Não altere as outras classes. O código fornecido lê quantos sensores vêm a seguir e, depois, um por linha: legacy ID FAHRENHEIT ou modern NAME CELSIUS. Ele encapsula cada termômetro antigo no seu adaptador e exibe todos os sensores. Para legacy 4 98.6 e modern Garden 21.5, a saída é:

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

Seu código deve ficar em thermometer_adapter.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 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 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