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 := 120Seu 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.
Desafio
FácilUm 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
LegacyThermometerencapsulado. get_sensor_name()retornaThermometer, um espaço e o código do termômetro, comoThermometer TH-4.get_celsius()retorna a temperatura em Celsius:(fahrenheit - 32) * 5 / 9, como umfloat.
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-4Seu 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()
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
1Fundamentos da POO
Arquivos externosIntrodução à POOClasses vs. objetosA palavra-chave selfMétodosPropriedadesConstrutor (_init)Revisão - Calculadora simples4Polimorfismo
Revisitando a Sobrescrita de MétodosDuck TypingClasses e Métodos AbstratosDesign de InterfacesRevisão - Calculadora de Formas7Sinais
O que é um sinal?Declarando e emitindoConectando-se a sinaisSinais com argumentosRevisão - Sistema de saúde10Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão Composite2Propriedades de Classe
Variáveis de Instância vs. EstáticasFunções EstáticasMétodos Setters de PropriedadeMétodos Getters de PropriedadePrivado por ConvençãoRecapitulando: Gerenciador de Conta Bancária5Encapsulamento
Membros públicos e privadosValidação com settersOcultação de informaçõesPropriedades somente para leituraRevisão - Sistema de registros de alunos8Conceitos Avançados de POO
Composição vs. HerançaClasses InternasNós como ComponentesRefCounted vs. NodeEnums em Classes3Herança
Herança básicaA palavra-chave superSobrescrita de métodosCadeias de herançaVerificações de tipo com isRevisão - Hierarquia de funcionários6Métodos especiais
Introdução aos métodos virtuaisO método _to_stringIteradores personalizadosRevisão - Lista personalizada9Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão ObserverPadrão StrategyPratique por conta própria: Compilador de GDScript online