No vÃdeo de hoje vamos falar sobre dois padrões de projeto. Os padrões Método Fábrica, Factory Method e Fábrica Abstrata, Abstract Factory. Os dois padrões são do livro Design Patterns, Elements of Reusable Object-Oriented Software. O livro da Gang of Four, ou GoF para os mais Ãntimos. Então vamos começar pelo Método Fábrica, ou Factory Method. O objetivo desse padrão é o seguinte: Definir uma interface para a criação de objeto mas delegar para as suas subclasses definirem qual a classe que será instanciada. Então a gente usa isso quando a gente quer criar novo método mas a gente não quer definir, deixar hard coded explÃcito no nosso código, qual é que é o tipo especÃfico da subclasse que vai ser criada. O Método Fábrica permite a uma classe deixar para as suas subclasses a definição dos tipos especÃficos com as quais se trabalhará. Como funciona isso? Vamos supor que a gente tem cliente que é alguém que vai usar, ele precisa criar uma nova instância de determinado objeto e esse objeto, vamos supor que é produto, produto. Uma opção mais normal, que é o que a gente está acostumado quando não usa esse padrão, é simplesmente faz x recebe newproduct1. A gente usa o operador new, da nossa linguagem de programação, para criar uma nova instância. A desvantagem disso é que o nosso código fica muito acoplado aquele tipo de produto1 especÃfico. Então, não só vai ter o produto1, escrito explicitamente no código do nosso cliente, como se forma uma linguagem fortemente tipada como Java ou C++, vai aparecer aquele tipo de produto1 várias vezes no nosso código. Todo o código do cliente vai estar ligado ao produto1, se a gente precisar fazer alguma alteração, por exemplo, vez de usar o produto1, usar outro produto2, a gente vai precisar mexer vários lugares. Para evitar isso, dar essa maior flexibilidade, tornar o cliente independente daquele tipo especÃfico de produto que ele usa, a gente usa o Factory Method. Como é que a gente faz? A primeira coisa, vez de o cliente ter uma referência para produto especÃfico, ele vai ter uma referência para uma superclasse abstrata, ou no caso de Java, pode ser uma interface, uma referência para uma interface, que define quais são as operações que eu vou precisar usar daquele produto, mas sem dizer qual é a classe do produto, dizendo apenas qual é a classe abstrata ou qual é o interface que aquele produto vai implementar. E na hora que for criar o produto, vez de a gente fazer o new e o nome da classe especÃfica, a gente usa outro objeto que vai ser esse objeto criador, creator. Esse objeto criador vai ter método, chamado createProduct que é quem vai realmente fazer a instanciação. Mas de novo, essa Creator é uma classe abstrata, você está vendo que está itálico aqui, representando que é abstrata. E para cada tipo especÃfico de produto que a gente quer ter, a gente cria subclasses especÃficas, nesse caso creator1 e creator2 que aà sim, ele vai ter método, a implementação de método createProduct, que vai criar produto especÃfico. Então, dentro desse createProduct da Creator1 vai ter uma chamada newProduct one. Mas esse new produto1 vai ficar escondido do cliente. Então, dessa forma, a gente pode inclusive criar novos tipos de produtos aqui, produto três, quatro, cinco, seis. Pode criar e para fazer isso a gente simplesmente implementa eles aqui e depois implementa criador que vai criar aquele tipo de produto especÃfico. A gente faz isso, sem mudar o código do cliente. O código do cliente fica imutável e a gente pode acrescentar novos produtos, tipos de produtos. Isso torna o código do cliente muito mais flexÃvel. Então, quais são as consequências de a gente adotar esse padrão? Ele desacopla o cliente dos tipos de produto especÃficos que o cliente usa. Ele remove da classe cliente todo o conhecimento sobre as subclasses especÃficas de produto. A gente deixa esse conhecimento escondido nas subclasses ou nos criadores. Permite que o sistema use tipos diferentes de produtos diferentes momentos. Eu posso executar o sistema usando determinado tipo de produto e depois, executar de novo, utilizando tipo de produto diferente. Permite que o programa seja estendido dinamicamente tempo de execução. Pode ser até que é programa que está rodando, está execução num servidor Web, por exemplo, e eu carrego novo produto e esse cliente, esse programa, esse sistema Web, passa a funcionar com esse novo produto e talvez é produto que nem existia no momento que coloquei o sistema para rodar. Eu posso ter sistema Web, que fica na Web dias ou meses ou anos rodando. Depois que o sistema já está executando eu vou lá, crio novo produto, carrego a classe no sistema, copio o arquivo ponto class para o sistema. E dinamicamente carrego uma nova classe, novo tipo de produto. Então, quem criou o sistema, nem sabia que eu ia depois, criar esse produto, mas a gente permite desse tipo fazer sistema antigo funcionar com novos produtos e portanto eu tenho novos comportamentos, novas aparências visuais, por exemplo. Pode ser sistema Web, que tem uma certa aparência, funciona de jeito e é sistema muito grande, tem muitos usuários. Eu não quero mexer tirar o sistema do ar, mexer e colocar no ar. Então, eu posso simplesmente criar novo produto e plugo no sistema que está executando, e o Factory Method pode ajudar a gente a fazer isso. Uma coisa interessante é que apenas uma linha de código vai definir o tipo dos produtos usados, ao invés de ter o tipo escrito dezenas de lugares diferentes. Apenas quando eu escolho qual é o criador que eu vou usar é que eu pego determinado tipo especÃfico de produto. Uma desvantagem, uma consequência negativa desse padrão, é que ele aumenta o número de classes no sistema, pois precisa de ter uma classe abstrata creator extra ou então uma interface extra no caso de Java. Então, torna o sistema pouco mais complexo, dá flexibilidade mas torna o sistema mais complexo. Esse é o Factory Method, vamos olhar exemplo, no livro do GoF, vem exemplo de labirinto. No GoF é C++ e Smaltalk, mas na Wikipedia tem esse exemplo várias linguagens C#, Java. Vamos dar uma olhada. Essa é a página do Factory Method na Wikipedia. A gente vê as implementações C#, Java, PHP, Python. Vamos dar a implementação de Java. Então, como é que funciona? A ideia é jogo de labirinto. Onde labirinto é como se fossem várias salas, vários quartos separados, conectados por corredores e o que ele está falando aqui, à s vezes eu quero diferentes tipos de jogos, diferentes tipos de salas. E eu posso criar esses diferentes tipos de salas usando o padrão Factory Method. Então como isso funcionaria? Teria uma classe sala que pode conectar uma classe abstrata, que é tipo abstrato de sala. E tem método connect que recebe uma outra sala como parâmetro. E isso eu uso quando quero conectar duas salas do labirinto, de forma a que o jogador possa andar de uma sala até à outra sala, abrir uma porta e sair noutra sala, por exemplo. Eu tenho dois tipos de salas, que eu uso a herança para definir, que é o MagicRoom que é uma sala mágica e o OrdinaryRoom, uma sala ordinária comum. E jogo de labirinto vai ter uma lista de salas, que vai ser ArrayList Java, e no construtor, o que é que ele faz? Ele cria duas salas, conecta a sala e a sala dois e nessa lista de salas ele conecta essas duas salas. Então é mini labirinto, só tem duas salas e as salas estão conectadas, provavelmente quando você abre a porta sai de você entra no outro. Agora, note que esse makeRoom está chamando esse método Abstrato, makeRoom. Então o método makeRoom não está implementando. Então, esse é tÃpico Factory Method. Primeiro, é uma fábrica, porque ele fabrica salas, fabrica Rooms e é uma fábrica abstrata nesse sentido, porque o método é abstrato. Quem vai definir o tipo especÃfico da sala que é criada são as nossas subclasses. Depois tem a definição das subclasses. Então, por exemplo, tenho MagicMazGame, que é uma subclasse aqui do Maze game e ela implementa o makeRoom, fazendo o quê? Aqui sim, tem a chamado do new, lembra que a gente deixa o new escondido, ele faz new MagicRoom, cria uma sala mágica e nessa outra implementação OrdinaryMazeGame, ele cria, tem a chamada para o new OrdinaryRoom. Então, escondendo o new, que está hard coded numa classe especÃfica nessa subclasse, a gente torna este código aqui totalmente genérico. Inclusive, agora eu posso chegar e eu criar o meu tipo de sala e o meu tipo de subclasse de MazeGame com esse novo método Fábrica implementando, e ter jogo completamente diferente, com novas regras de jogo. Então esse é o padrão, só tem exemplo de uso. Esse é o padrão Factory Method implementando Java. Vamos voltar aqui para a nossa implementação. Implementação não, a nossa apresentação. Vamos para outro padrão que é o padrão Fábrica Abstrata, que é na verdade uma evolução do método Fábrica. E a gente vai ver que Fábrica Abstrata, o Abstrat Factory usa o método Fábrica.