Executando verificação de segurança...
4

[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.

Carregando publicação patrocinada...
4
2

Tipo...

class ArmaDecorator implements Arma {
    protected $arma; 

    public function __construct(Arma $arma) {
        $this->arma = $arma;
    }

    /** @override */
    public function montar() {
        $this->arma->montar();
    }

}

Essa classe decorator, aponta o método montar para o objeto principal $this->arma->montar()...
Mas, esse método montar, é justamente o método que estou decorando, então faz sentido.
Mas, e se a arma tivesse mais um método calibrar, por exemplo, que não vai fazer parte do Decorator?

2