Eu vou falar para vocês, agora, neste vídeo, sobre o 'Padrão Prototype', que é padrão que eu gosto muito, porque ele dá bastante dinamismo a sistema. É padrão bem interessante. É padrão do livro "Gang of four", que vocês já conhecem muito bem. E eu vou usar aqui como exemplo código que a gente viu quando eu falei sobre Fábrica Abstrata. Então é legal que vocês verem o vídeo da Fábrica Abstrata, caso não tenham visto ainda. Então o 'Prototype', ou protótipo, português, a idéia dele é ele ser outro daqueles padrões de criação de objetos que faz com que a gente não precise usar o 'new' e o nome da classe, que deixa o código muito amarrado. Ele nos dá uma outra forma mais flexível de criar objetos. E aqui como funciona? O tipo de objeto a ser criado é determinado por uma instância prototípica. Então, vez de a gente fazer 'new class', a gente pega uma instância e pede para aquela instância se clonar, criar clone; e, assim, a gente obtém, como resposta, esse novo objeto, que é clone daquela instancia. A gente chama isso de instância prototípica ou protótipo. Então, esse protótipo é clonado para produzir novos objetos. Tem várias vantagens. Quando a gente usa o prototype? Quando a gente quer evitar ter que implementar subclasses de uma classe criadora para cada tipo de objeto. Então quando a gente usa o padrão método fábrica, por exemplo, a gente tem que criar uma classe abstrata, 'creator', e depois várias subclasses criadoras. Uma para cada tipo de classe concreta que a gente tem. Quando a gente usa fábrica abstrata, também, a gente acaba com aquele monte de classes extras, uma para cada tipo de objeto que a gente quer criar. E aqui, usando o prototype, a gente evita de criar essas classes criadoras. A gente simplesmente pega uma instância qualquer e fala: clone-se! E daí, então, as classes desses objetos que vão ser clonados têm que oferecer o método clone, ou algum outro método com o nome parecido. Normalmente é clone. E esse clone, o que ele faz? Ele cria uma nova instância, mas ele copia todos os atributos do objeto para esse novo objeto que está sendo criado, esse clone. Dependendo do seu sistema, essas cópias de atributos talvez tenham que ser uma coisa meio recursiva, porque, às vezes, dos atributos é outro objeto. E daí você tem que, novamente, clonar esse outro objeto também. Depende do caso específico que você está trabalhando. Outro caso é quando o custo de criar novo objeto é muito grande. Então, vez de chamar o chamar o new na classe, a gente apenas cria objeto existente. Então, por exemplo, se você quer clonar, tem amigo que você gosta muito, só que ele é muito ocupado, você quer criar clone dele. Se você fosse criar outro amigo igual, você precisaria criar novo ser humano. O ser humano nasce bebê, daí tem que ir para o jardim de infância, tem que aprender a engatinhar, andar, depois ele vai para a escola, ele vai para a faculdade até chegar ao jeito que é o seu amigo. Demora muito tempo. Você não tem paciência para esperar tanto. Então o que você faz? Você pega o seu amigo que já está pronto ali e você fala: cria clone! Dai ele simplesmente cria outro idêntico a ele e pronto, já está pronto para usar. Não precisa ficar esperando aqueles 18 anos para ele chegar no ponto certo. Obviamente, isso é uma analogia com o sistema onde chegar objeto do jeito que a gente, você precisa de monte de operações muito pesadas computacionalmente. Então, vez de refazer tudo isso, simplesmente faz uma cópia, clone, do objeto e ele já está pronto para usar. Outro caso é quando a gente quer evitar uma série de 'if' e 'elses' quando você tem 'if´s' para ficar determinando qual é o tipo específico do objeto. E daí tiver comportamentos, criação de objetos, diferentes. Dependendo de tipos, como a gente viu no nosso exemplo anterior da fábrica abstrata, se a gente usa protótipo, simplesmente, pega o objeto que a gente quer e clona imediatamente. É muito mais fácil. Eu vou mostrar exemplo, agora, de código onde a gente vai pegar aquele código da fábrica abstrata que a gente tinha visto, que não era muito bonito, e vai torná-lo mais bonito. Então, o que não estava muito bonito aqui? Essa fábrica abstrata, 'animal factory', tem esse método 'creator', que é o método fábrica, mas ele tem essa série de 'if´s' e 'elses' para ver aqui que tipo de especial de animal deve ser criado. Se for 'dog', 'stringdog', ele faz new dog; se for 'duck', ele faz new duck. Se tivessem outros tipos, teriam outras 'if´s' e 'elses' aqui, que é uma coisa totalmente, código macarrônico, totalmente não orientado a objetos. Então, o protótipo ajuda a gente a tornar isso aqui mais orientado a objetos. Quer ver como vai ficar simples? Então, para remover esses 'if´s' e 'elses', vai ser simples A gente vai criar aqui 'hashmap'. Java, tem tipo de coleção específica que é mapa, que se chama hashmap. Ele mapeia tipo de coisa outra. Então, a gente vai criar mapa que vai mapear strings com nomes de animais para objeto do tipo animal. Então, porque eu vou querer pegar esse 'stringdog' e mapear para a classe dog. Eu vou chamar isso aqui de protótipos de animais e aqui vai ser 'new hashmap', aqui diamante. Tudo bem, agora, eu preciso dar importe aqui. Importe hashmap; fez o importe. Agora, eu preciso criar o construtor do meu 'animal factory' para alimentar esse protótipo de animais com os protótipos que eu preciso. Então, tem o método 'put', que é esse método aqui, 'put'. E eu vou falar: Onde? Quando alguém pedir dog, você devolve uma instância. Eu vou criar a instância aqui, esse new; você devolve dog, uma instância de dog. E a mesma coisa equivalente aqui para o duck. Se tivessem outros, mas colocaria várias entradas. 'New duck' aqui. Então pronto, já criei aqui esse meu mapa de protótipos. E, agora, o creator vai ficar super simples. Eu posso apagar esse monte de 'if' e 'elses', esse 'return new' aqui, esse monte de 'if' e 'else' nada a ver. E eu simplesmente vou falar o seguinte. Eu pego o protótipo de animais ponto 'get'; e aí passa como parâmetro animal. Animal não. Eu vou passar como parâmetro o nome do animal, que é esse 'animaltype' aqui. 'Animaltype'. Isso aqui vai devolver o quê? Vai devolver uma instância prototípica. E daí eu posso chamar o clone e esse é o valor que eu vou devolver. Então, aquele monte de 'if´s' e 'else' vira uma única linha aqui. Então, protótipos de animais ponto 'get', 'animaltype', isso vai devolver a instância prototípica, eu chamo o clone e pronto, acabou. Ficou muito mais simples. Só que não acabou totalmente. Por que está vendo? Está dando erro. Eu tenho que implementar esse método clone aqui. Então, o método clone não está definido no tipo animal. Então, eu vou ter que ir lá no tipo animal e acrescentar novo método. Então, vai ter método clone que vai devolver alguém do tipo animal. Então, a interface animal passou a ter o clone e, agora, todo mundo que implementa essa interface animal; e fazer a clonagem. Então, por exemplo, o cachorro também vai ter algo assim. 'Public Animal Clone'. Ele vai ter que implementar isso aqui. Como ele implementa? Eu vou fazer uma implementação o mais simples possível. Simplesmente novo cachorro. Se o cachorro tivesse atributos interessantes, aí teria que clonar os atributos também. Essa classe aqui é bem simples, ela não tem atributos. Não precisa clonar nada. E, agora, eu vou também fazer a mesma coisa com o pato. Eu criei o clone no pato. Só que eu tenho que criar aqui, 'duck'. Pronto. Tem algum erro que eu deixei passar ainda. Qual é o erro? Vamos ver os erros. [SOM] [ESTRANGEIRO] Sabe qual é o erro? Eu não tinha salvo. Eu não tinha salvo. E aqui, o dog. Tem algum erro? Também não tem nenhum erro. Não esqueça de salvar os seus arquivos. Então, vocês viram. Fica pouquinho mais complicado, as minhas classes, porque eu preciso desse clone. Por outro lado, olha como ficou simples, aqui, a fábrica abstrata. E acrescentar novos tipos de objetos, eu não preciso criar nenhuma classe nova, só a classe do novo tipo. Então, se for novo animal, aqui, basta a classe do animal. Não precisa criar essas outras classes acessórias só para fazer a criação. Eu crio essa nova classe animal, tendo o método clone e, automaticamente, insiro aqui uma linha única para ter a instância prototípica. E, pronto, a minha fábrica abstrata já está muito mais enxuta, muito mais genérica e flexível. Vamos só rodar para ter certeza de que está tudo certo aqui. Rodar esse exemplo e falar: esse exemplo aqui cria cachorro de cor marrom latindo. E note que eu não precisei trocar nada no código. A fábrica abstrata continua funcionando do mesmo jeito ali, simplesmente. A diferença é que, internamente, vez de usar aquele monte de 'if´s' e 'else', agora está usando o padrão protótipo. Então, o padrao protótipo nos ajuda bastante. A idéia básica dela é que ao invés de você fazer new uma nova classe, você chama clone uma instância. O prototype oferece bastante flexibilidade evitando a chamada explícita ao new. Torna o código mais desacoplado. Ele traz uma complexidade extra, que é criar esses métodos clone. Mas é uma forma poderosa de desacoplar código de tipos e classes específicas tornando o código mais enxuto. Então, eu espero que vocês tenham gostado. Abraço e até o próximo padrão. [SOM] [SOM]