Padrão Decorator
Parte da seção Programação orientada a objetos do Journey de GDScript da Coddy. Lição 52 de 65.
O padrão Decorator adiciona comportamento a um objeto envolvendo-o em outro objeto com os mesmos métodos. Cada wrapper chama o objeto dentro dele e adiciona sua própria parte, e os wrappers podem ser encadeados em qualquer ordem.
# weapon.gd
class_name Weapon
extends RefCounted
func get_damage() -> int:
return 10
func describe() -> String:
return "Sword"Um decorador estende Weapon, então pode ser usado onde se espera uma arma, e mantém a arma que envolve:
# fire_enchant.gd
class_name FireEnchant
extends Weapon
var inner: Weapon
func _init(wrapped: Weapon) -> void:
inner = wrapped
func get_damage() -> int:
return inner.get_damage() + 5
func describe() -> String:
return inner.describe() + " + Fire"SharpEnchant é escrito da mesma forma, mas seu get_damage() retorna inner.get_damage() * 2 e seu describe() adiciona " + Sharp".
# main.gd
var weapon: Weapon = Weapon.new()
print(weapon.describe(), ": ", weapon.get_damage())
weapon = FireEnchant.new(weapon)
weapon = SharpEnchant.new(weapon)
print(weapon.describe(), ": ", weapon.get_damage())Sword: 10
Sword + Fire + Sharp: 30As chamadas seguem para dentro: SharpEnchant pergunta a FireEnchant, que pergunta à espada. A espada retorna 10, o fogo transforma esse valor em 15, e o afiado dobra esse valor para 30. Na outra ordem, FireEnchant.new(SharpEnchant.new(Weapon.new())), o dano é 10 * 2 + 5, ou seja, 25.
Sem decoradores, cada combinação precisaria de sua própria subclasse: FireSword, SharpSword, FireSharpSword e assim por diante. Com eles, duas classes pequenas abrangem todas as combinações, e um novo encantamento exige apenas mais um arquivo.
Desafio
MédioUma cafeteria prepara bebidas com decoradores. Beverage (beverage.gd) declara cost() e description(); Espresso (espresso.gd, $3) e Tea (tea.gd, $2) já estão escritos. Cada decorador armazena em inner a bebida que envolve (os construtores já estão escritos). Sobrescreva cost() e description() em:
Milk: custa1a mais e adiciona+ Milkà descrição.Mocha: custa2a mais e adiciona+ Mocha.Large: dobra o custo de tudo o que está dentro dele e colocaLargeno início da descrição.
O código fornecido lê quantos pedidos virão e, em seguida, um pedido por linha: a bebida (espresso ou tea) e seus adicionais, aplicados da esquerda para a direita. Para espresso milk large e tea mocha milk, a saída é:
Large Espresso + Milk: $8
Tea + Mocha + Milk: $5Seu código deve ficar em milk.gd, mocha.gd e large.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 count := int(OS.read_string_from_stdin())
for i in count:
var words := OS.read_string_from_stdin().split(" ")
var drink: Beverage = Tea.new()
if words[0] == "espresso":
drink = Espresso.new()
for extra in words.slice(1):
match extra:
"milk":
drink = Milk.new(drink)
"mocha":
drink = Mocha.new(drink)
"large":
drink = Large.new(drink)
print("%s: $%d" % [drink.description(), drink.cost()])
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