Menu
CoddyTech

Patron Adaptateur

Fait partie de la section Programmation orientée objet du Journey GDScript de Coddy. Leçon 51 sur 65.

Le modèle Adaptateur permet à un objet de fonctionner avec du code qui attend des méthodes différentes. L’adaptateur enveloppe l’objet et transforme chaque appel attendu en un appel que l’objet comprend.

Une ancienne classe d’un projet précédent stocke la santé sous forme de deux nombres :

# old_monster.gd
class_name OldMonster
extends RefCounted

var life := 30
var max_life := 120

Votre HUD affiche tout ce qui possède get_label() et get_hp_percent(). Un Knight possède déjà les deux (il renvoie "Knight" et 80), mais OldMonster ne possède ni l’un ni l’autre :

# health_display.gd
class_name HealthDisplay
extends RefCounted

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

L’adaptateur contient un OldMonster et fournit les deux méthodes appelées par l’affichage :

# 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 n’ont changé. C’est important lorsque vous ne pouvez pas ou ne devez pas modifier une classe : elle provient d’un plug-in, appartient à une autre équipe ou de nombreux scripts dépendent de ses noms.

L’adaptateur transmet chaque appel et convertit les données au passage, ici deux nombres en un pourcentage. Multipliez avant de diviser : avec des entiers, 30 / 120 * 100 vaut 0, tandis que 30 * 100 / 120 vaut 25.

challenge icon

Défi

Facile

Un tableau météo affiche des capteurs qui possèdent get_sensor_name() et get_celsius(), comme ModernSensor (modern_sensor.gd). Le tableau se trouve dans weather_board.gd. Les anciens thermomètres (legacy_thermometer.gd) proposent uniquement read_fahrenheit() et get_code(). Écris l’adaptateur ThermometerAdapter :

  • Le constructeur stocke le LegacyThermometer enveloppé.
  • get_sensor_name() renvoie Thermometer, une espace et le code du thermomètre, comme Thermometer TH-4.
  • get_celsius() renvoie la température en Celsius : (fahrenheit - 32) * 5 / 9, sous forme de float.

Ne modifie pas les autres classes. Le code fourni lit le nombre de capteurs qui suivent, puis un capteur par ligne : legacy ID FAHRENHEIT ou modern NAME CELSIUS. Il enveloppe chaque ancien thermomètre dans ton adaptateur et affiche tous les capteurs. Pour legacy 4 98.6 et modern Garden 21.5, la sortie est :

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

Ton code va dans thermometer_adapter.gd. main.gd contient le code d’entrée/sortie fourni et ne peut pas être modifié.

Essayez vous-même

extends Node

func _ready():
	# Code d’entrée/sortie fourni : conservez-le tel quel
	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 iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Compilateur GDScript en ligne