Eu não iria fazer vídeo sobre o Decorator, mas vocês insistiram, então aqui vai vídeo sobre o padrão de projeto Decorator. Ele é padrão estrutural e o objetivo é adicionar novas responsabilidades a objeto dinamicamente. A ideia é oferecer uma alternativa flexível à herança, de forma a estender o comportamento, a funcionalidade de determinado objeto, mas poder fazer isso tempo de execução. Vamos dar exemplo aqui que é baseado no exemplo do Gof. O contexto aqui é sistema que você tem uma interface gráfica com janelas e você pode ter diferentes tipos de widgets, que são elementos gráficos, nessa interface gráfica. Então, vamos supor que você tenha TextView, que é simplesmente retângulo com texto dentro, onde o usuário pode digitar texto, pode ler texto. Mas só isso não é algo muito interessante. Normalmente, quando você quer poder ler o texto, você precisa de uma barra de rolagem, pode ser uma barra de rolagem vertical ou horizontal, por exemplo, aqui uma vertical e horizontal. Uma forma de implementar isso usando o padrão Decorator é você ter objeto simples, básico, que é o TextView, e depois ter Decorator, nesse caso, chamado ScrollDecorator, que acrescenta comportamento extra das barras de rolagem cima do TextView. E aqui tem outro exemplo também, que é esse BorderDecorator que ainda acrescenta essa borda aqui. Então, você pode construir sistema de forma que você tenha TextView que é decorado por ScrollDecorator que é decorado por BorderDecorator. Você poderia ter outras decorações cima também, poderia ter uma decoração que acrescenta título aqui na janela, outra decoração que acrescenta aqueles ícones de fechar a janela, minimizar a janela. Tempo de execução, a gente vai ter objeto aqui, uma instância desse TextView, mas torno dele a gente vai ter ScrollDecorator. às vezes se chama de wrapper também. Objeto que envolve esse TextView e que acrescenta certo comportamento ou modifica o comportamento do objeto que ele está envolvendo. Ele vai ter uma referência aqui para o objeto. Então, nesse caso uma variável component que aponta para esse TextView e, torno do ScrollDecorator, você tem BorderDecorator. Então, você tem dois decoradores: decorando o próximo e decorando o TextView por final. Então, como é que é o diagrama aqui? Seria sistema que a gente tem componentes visuais que aparecem na interface gráfica. Desses componentes visuais é o TextView. E daí você tem todo conjunto de decoradores aqui. Esse decorador também é uma componente visual, é uma subclasse e tem uma referência para a componente aqui, à qual ele está acrescentado certo comportamento ou alterando o comportamento. E daí nesse caso a gente tem, note esse Decorator é uma classe abstrata. A gente tem duas classes concretas aqui, que são o ScrollDecorator e o BorderDecorator, que são subclasses Decorator, é importante portanto ter uma referência aqui. Essa aqui é a estrutura genérica do Decorator. Como é que é então? Generalizando a imagem anterior, a gente tem uma componente, uma componente concreta e o decorador com as várias implementações concretas do decorador. Para deixar isso mais claro aqui como funcionaria isso Java, eu fiz aqui uma implementação que acho que vocês vão gostar. O problema é que dá pouco de fome essa minha implementação. Como é que é? Então, aqui no lugar dessa componente genérica aqui, eu fiz a interface Pizza. Essa interface Pizza tem único método, que se chama preço, que vai devolver o preço dessa pizza. Daí eu tenho também uma implementação concreta dessa interface Pizza que se chama PizzaDaNona. Como que funciona a PizzaDaNona? Ela implementa a Pizza e ela tem uma lista de ingredientes aqui. Você está vendo os recheios. E daí, quando a gente constrói, a gente pode passar como parâmetro essa lista de ingredientes e como que é calculado o preço da pizza? Simplesmente eu percorro todos os ingredientes pegando os valores e somo e devolvo e esse dá o preço da pizza. A PizzaDaNona é uma pizza muito simples, não é? Mas daí eu tenho a classe PizzaDecorator. Essa classe PizzaDecorator também implementa aqui a interface Pizza só que ele tem duas coisas interessantes aqui: primeiro, quando eu crio PizzaDecorator, decorador de pizza, eu passo uma pizza como parâmetro, que é a pizza que eu estou decorando, e eu tenho como atributo, guardo ali uma referência para a pizza decorada, está bem? Então, esse PizzaDecorator seria como o Decorator aqui, não é? Eu guardo uma referência para uma Pizza, que é a pizza decorada. Esse aqui é uma classe abstrata. Está vendo? É abstract PizzaDecorator, porque eu não vou ter instâncias disso, eu vou ter instâncias de quem? Eu criei três tipos de decoradores de pizza: é o MassaIntegral, a BordaRecheada e a Extragrande. Então, a MassaIntegral, como é que é? A MassaIntegral extende esse PizzaDecorator, mas ela é uma classe concreta, então eu posso ter instâncias dessa MassaIntegral. Quando eu crio esse decorador de MassaIntegral, eu tenho que passar uma pizza como referência aqui para o construtor, então vira uma de massa integral. E o preço da pizza de massa integral qual é? É o preço da pizzaDecorada, que é quem eu estou envolvendo, mais cinco reais extra. E daí tem a BordaRecheada. BordaRecheada é bem equivalente. A única diferença é que o preço é o preço da pizza que estou decorando mais dez reais. E finalmente eu tenho a pizza ExtraGrande. A pizza ExtraGrande é a mesma coisa só que o preço dela, quanto é? É o preço da pizzaDecorada mais 30%, vezes ponto três. E daí, para exemplificar isso, eu fiz aqui uma classe que chamei de PizzariaDaNona. O que eu faço nessa classe aqui? Primeiro eu crio HashMap de ingredientes. Eu falo que a massa básica da pizza custa dez reais, mussarela cima da pista custa 20, tomate cinco e manjericão cinco. E daí eu crio uma pizza, que eu chamei marguerita, que é uma nova PizzaDaNona com esses ingredientes. Então, essa aqui é a minha marguerita. Seguida, eu crio uma super marguerita. Então, como eu crio essa super marguerita? Colocando decoradores torno da minha pizza marguerita. Então, como é que funciona isso aqui? Vou fechar aqui para dar para enxergar melhor. Então, eu pego uma pizza marguerita, que é essa que eu tinha criado antes, e crio uma nova MassaIntegral, decorador MassaIntegral, passando a pizza marguerita como parâmetro. E o resultado disso eu passo como parâmetro para o decorador de BordaRecheada. O resultado disso eu passo como o parâmetro para o ExtraGrande. Então, eu vou ter uma pizza marguerita com MassaIntegral e BordaRecheada de tamanho ExtraGrande. Então, se eu mandar imprimir aqui, a minha pizza ustará tanto. Eu simplesmente falo minhaSuperMarguerita ponto preço e daí magicamente o preço vai sendo calculado de acordo com essa minha sequência de decoradores que eu coloquei ali. Então, vamos executar para ver se está funcionando? Vou mandar executar aqui. Minha pista, minha pizza, pista, então pizza. Minha pizza custará 71 reais, está bom? Só de curiosidade, eu coloquei aqui breakpoint nessa linha e vamos mandar executar no debugger para a gente ver aqui, no depurador. Que é interessante a gente ver como é que funciona. Então, está vendo tem a pizza marguerita e aqui a minhaSuperMarguerita. Se eu for olhando aqui dentro, a gente vê que essa minhaSuperMarguerita é uma pizza do tipo ExtraGrande, mas ela contém uma pizzaDecorada dentro dela e a pizzaDecorada que está dentro dela é uma pizza de BordaRecheada. Agora se eu for olhar essa BordaRecheada, a pizzaDecorada dentro dela é uma pizza de MassaIntegral. Agora se eu for olhar essa MassaIntegral, a pizzaDecorada dentro dela é uma PizzaDaNona, que é aquela classe concreta básica. Se eu for olhar na PizzaDaNona, aí sim ela já tem os ingredientes, que é o HashMap. Então, a gente vê aqui é Muzzarela e assim por diante. Então, aqui manjericão. Aqui o preço do manjericão, o manjericão custa cinco reais para colocar. Então, a gente vê que tem essa estrutura hierárquica, uma coisa, objeto torno do outro sempre acrescentando novo comportamento ou modificando pouco o outro comportamento. Esse aqui é exemplo. Espero que não tenha dado muita fome vocês. Continuando então aqui, resumindo: o padrão Decorator permite adicionar novas responsabilidades a objeto dinamicamente. Note que a gente pode escolher quais, qual a ordem das responsabilidades que a gente cria. A gente pode acrescentar, remover e é uma coisa muito dinâmica. Decoradores oferecem uma alternativa mais flexível para herança e podem ser usados para adicionar a objetos individuais, ao invés da classe inteira. Quando a gente usa herança, a gente cria uma nova classe. Aqui não, a gente pode ter vários objetos diferentes e cada objeto a gente escolhe quais decoradores a gente quer acrescentar tempo de execução. Então, é muito mais flexível. Há o custo adicional, porque a gente tem que criar toda essa nossa estrutura, tem que tomar cuidado para ver que coisa vai ficar, vai dar certo, o compilador não nos ajuda tanto, porque muita coisa dinâmica acontece, mas tem padrão com bastante potencial, de bastante flexibilidade. Espero que vocês tenham gostado. Por hoje é só.