[Dúvida] [TS] Implementação do Design Pattern Decorator no Typescript
Boa noite, galera! Tudo bem?
Hoje, eu estava tendo aula de APS 2 (ANÁLISE E PROJETO DE SISTEMAS II) na faculdade, estudando mais especificamente o padrão de projeto Decorator.
A professora utiliza o Java para ministrar a aula, mas eu recorri ao TypeScript, pois o utilizo em ambiente de trabalho e gostaria de aproveitar o momento para exercitar e aprimorar minhas skills com minha ferramenta de trabalho.
Seguindo a estrutura arquitetada em aula, me vi numa situação duvidosa ali no TypeScript:
Temos uma base de código que, na primeira aula, foi trabalhado o padrão Strategy, para a criação de um sistema de Drinks, bem simples!
Basicamente, temos uma classe abstrata Drink que se desdobra em três drinks concretos Caipirinha, Cosmopolitan e Gin Tônica. Cada bebida possui uma maneira de ser preparado, e uma maneira de ser servido. Isso tece o conteúdo abordado em Strategy.
Agora, com o Decorator, temos que adicionar alguns comportamentos "decorativos" a estes drinks já instanciados.
Por exemplo, um Decorator Amendoim, que adiciona um método servirAcompanhamento à classe da bebida quando decorada.
Portanto, a decoração de uma caipirinha com acompanhamento de Amendoim ficaria assim:
let drink = new Caipirinha();
drink = new Amendoim(drink);
O grande problema é que agora drink recebeu uma nova instância de Drink sem a aplicação das estratégias de preparo e serventia da Caipirinha!
Isso porque, semanticamente falando, a classe decoradora Acompanhamento
é, de certa forma, uma instância nova de Drink, que recebe uma referência à um drink já instanciado:
export default abstract class Acompanhamento extends Drink {
possuiAcompanhamento: boolean = true;
drink: Drink;
constructor(drink: Drink) {
super();
this.drink = drink;
}
abstract servirAcompanhamento(): void;
}
O drink Caipirinha
outrora instanciado, ficou guardado agora na referência this.drink
.
Com isso, minha classe decoradora abstrata precisa sair implementando novamente TODOS os métodos da classe principal Drink
apontando para o método do this.drink
... Caso contrário, é executado o método sobre uma instância nova e vazia de Drink, sem nenhuma estratégia.
Mas, sair definindo novamente todos os métodos da classe principal fere o princípio Open/Close da SOLID.
Todos os conteúdos que encontro na internet sobre exemplos da implementação do Decorator, a classe principal possui apenas um método que será, justamente, o método modificado pelo decorador.
https://codesandbox.io/s/aps2-20212-dddq0d
Aqui está a base de código que estou trabalhando, para quem quiser observar mais a fundo.
E meu Discord, DenisWilton#8539
, caso alguém queira entrar em contato mais direto.