Fábrica Abstrata que é na verdade uma evolução do método Fábrica e a gente vai ver que Fábrica Abstrata, ou Abstract Factory, ele usa o método Fábrica. Aqui eu segui bem o jeito que ele é apresentado no livro GOF então 87 é o número da página do livro GOF onde aparece o método Fábrica Abstrata. Então o objetivo do Fábrica Abstrata prover uma interface para criação de famÃlias de objetos relacionados sem especificar sua classe concreta. Então note que uma grande diferença aqui é que são famÃlias de objetos, são vários objetos diferentes que pertencem a uma mesma famÃlia. Vamos ver a motivação que o livro dá para a gente. Considere uma aplicação com interface gráfica, visual, que é implementada para plataformas diferentes, então por exemplo para UNIX para Windows, para Macintosh. Então é o mesmo software que tem que funcionar três plataformas diferentes. Então lá no UNIX ele usa uma biblioteca chamada Motif, no Windows ele vai usar as bibliotecas da Microsoft para a construção de interfaces gráficas, no iOS vai usar as bibliotecas da Apple para construir a interface gráfica. Então cada vez que ele cria novo elemento gráfico na interface gráfica, botão uma janela, uma barra de rolagem, são comandos diferentes nesses três sistemas operacionais para criar então as classes implementando os elementos gráficos não pode ser definidas estaticamente no código. Quando eu estou rodando lá no Linux, por exemplo, eu não posso falar new Windows button, para criar botão daquela biblioteca da Microsoft. Não, porque no Linux não existe biblioteca da Microsoft, é new numa outra classe. Cada sistema operacional tem que fazer new numa classe diferente, então a gente precisa ter aqui uma implementação diferente para cada ambiente. Às vezes até no mesmo ambiente, por exemplo, o Firefox no mesmo ambiente, no seu Linux, por exemplo, você pode ter diferentes aparências, que eles chamam de diferentes Look and Feel, são diferentes aparências do seu sistema e pode ser que então a gente quer chavear de uma aparência para outra. Ou seja a gente está na numa aparência Dark, é tudo meio preto, escuro assim, o botão vai ser botão preto, a barra de rolagem vai ser uma barra de rolagem azul escura. Já se você vai para uma outra aparência Light, daà todos os botões são diferentes, todos os elementos gráficos são diferentes, vai ser tudo clarinho. Mas então note que são famÃlias e a gente quer manter a consistência entre essas famÃlias, a gente não quer misturar botão preto numa interface light, não quer criar botão do Windows quando está rodando no Linux, não que aà nem daria certo, vai dar erro termos de execução. A gente pode solucionar esse problema definindo uma classe abstrata para cada elemento gráfico então o botão vai ter abstract button e daà tipos especÃficos: o Linux button, o Windows button e o Mac iOS button, por exemplo. Utilizando diferentes implementações para cada aparência ou para cada ambiente. E daà ao invés de criarmos as classes concretas diretamente com o operador new, no nosso código a gente vai utilizar uma Fábrica Abstrata para criar esses objetos tempo de execução. E o código do cliente não sabe qual classe concreta a gente está utilizando, isso vai ficar escondido lá dentro da fábrica. Quando que isso aqui é aplicável? A gente usa uma Fábrica Abstrata quando sistema deve ser independente da forma como seus produtos são criados e representados. Sistema deve poder lidar com uma famÃlia de vários produtos diferentes e você quer prover uma biblioteca de classes de produtos mas não quer revelar as suas implementações, quer revelar apenas as suas interfaces e deixar a implementação escondida. Então como é que funciona, como é o diagrama UML desse padrão Abstract Factory? É o seguinte: então você tem o cliente aqui e o cliente ele vai ter referências para os produtos abstratos, então ou para uma classe abstrata ou para uma interface. Então nesse caso o cliente tem uma referência, tem apontador, uma referência para abstract product A e para abstract product B. Então ele vai lidar com objetos desse tipo Abstrato e desse tipo Abstrato. Ele não tem referências diretas para produtos diretos especÃficos aqui, para o Product A1, Product A2, Product B1, Product B2. Você está vendo, não tem referências especÃficas, a referência é sempre para a classe abstrata. E ele tem também apontador, uma referência para uma Fábrica Abstrata que lá tem os métodos Crie o Produto A, Crie o Produto B, que também são abstratos. E daà sim aqui a gente escolhe as famÃlias de produtos. Então a primeira famÃlia de produto, representado por essa ConcreteFactory1, aà sim, ele tem os métodos createProduct, que daà sim ele tem new que vai criar aqui o ProductA1 ou o ProductB1. E essa outra famÃlia de produtos, a famÃlia concreteFactory2 ele vai criar o productA2 ou o productB2. Desse jeito o cliente também não vai correr o risco primeiro de criar produto errado, então por exemplo isso pode ser os elementos gráficos do Windows e os elementos gráficos do Linux. O cliente, se ele está no ambiente Linux ele vai instanciar uma Fábrica Abstrata aqui do tipo especÃfico de Linux, e daà automaticamente toda a vez que ele fala crie produto A, crie produto B, crie produto C já vai vir produto especÃfico para Linux, ele não corre o risco de misturar as famÃlias de produtos, então você mantém essa coerência nos estilos. A mesma coisa foi a aparência. Você quer a aparência de videogame que tem uma, pode ser o mesmo videogame, com uma aparência espacial ou de velho Oeste? Se você tem uma fábrica de velho Oeste, que só gera produtos de velho Oeste e outra fábrica espacial que só gera produtos do espaço sideral, você não corre o risco de no seu jogo aparecer cavaleiro, como chama? Pistoleiro cima de cavalo numa nave espacial, isso não vai acontecer porque você garante a uniformidade. Se bem que até tem filme engraçado que é de uns alienÃgenas ali que chegam no velho Oeste mas isso aà é caso excepcional. Então vamos lá. Quais são os participantes aqui? Então a gente tem a Fábrica Abstrata, que no caso desse exemplo das interfaces gráficas, seria uma WidgetFactory, que é uma Fábrica Abstrata que gera os elementos gráficos da sua interface gráfica, daà você tem Fábricas concretas que vão ser subclasses, que pode ser aquela versão dos widgets do Windows, do UNIX, do Motif ou do Windows. E daà você vai ter produtos abstratos. Produtos abstratos pode ser uma janela, barra de rolagem, campo de texto e daà os produtos concretos. Então uma janela Motif do Linux, ou scrollbar para o Windows, são produtos bem especÃficos. E daà o cliente usa apenas as interfaces declaradas pela AbstractFactory e pelas classes AbstractProduct, assim ele pode funcionar diferentes momentos com diferentes famÃlias de produtos. E normalmente apenas uma instância de ConcreteFactory é criada tempo de execução, você não vai ter várias. E essa instância cria objetos através desses métodos ConcreteProduct correspondentes à famÃlia de produtos e ele vai ter vários métodos, para cada tipo de produto que ela gera. E essa AbstractFactory ela delega a criação dos objetos para as suas subclasses que são as ConcreteFactory. Consequências. Primeiro esse padrão isola as classes concretas dos clientes que as usam. Facilita a troca de famÃlias de produtos. Basta trocar uma única linha de código pois a criação da fábrica concreta aparece único ponto do programa. Então trocando uma única linha de código você troca toda uma famÃlia de produto. Promove a consistência do produto. Se não há o perigo de misturar objetos de famÃlias diferentes. Uma desvantagem é que dificulta a criação de novos produtos ligeiramente diferentes Porque toda a vez que você coloca novo produto tem que modificar a Fábrica Abstrata, modificar todas as Fábricas Concretas, então dá para trabalhão ali para colocar novo produto. É o preço que você tem a pagar por esse ganho de flexibilidade. Então, de novo, tem aquilo que a gente chama de trade off, você ganha flexibilidade mas você perde pouco complexidade, você vai ter mais classes no seu sistema. Então só vale a pena usar esse padrão quando essa flexibilidade vai ser útil, porque se o programa vai ficar mais complexo, você não quer complexidade a mais à toa, você só coloca essa complexidade a mais se ela for útil para você. Então isso é como qualquer padrão de projeto, a gente não fica usando padrão só por usar padrão só porque é legalzinho usar padrão, não. Você só vai usar o padrão quando ele te traz benefÃcio concreto para aquilo que você está precisando fazer agora. Você não coloca padrão se falar " talvez daqui a 6 meses eu vou precisar usar isso" não. Você não faça isso, só quando ele vai trazer ganho para você hoje, implementando isso hoje. Vamos dar uma olhada uma implementação, como é que a gente implementa? As Fábricas Abstratas geral são implementadas como Singleton porque não faz sentido ter várias Fábricas no seu sistema, geral você só vai ter uma portanto é Singleton. Na Fábrica Abstrata a gente cria método fábrica para tipo de produto. Então cria botão, cria barra de rolagem, cria campo de texto, e daà cada Fábrica concreta vai implementar o código que cria os objetos de fato. Se a gente tem muitas famÃlias de produtos, pode ser que você tenha sistema lá naquele videogame por exemplo, você pode ter 40 coisas diferentes que podem aparecer na tela do vÃdeogame daà isso vai gerar excesso de Fábricas Concretas. Você vai precisar de 40 fábricas concretas para cada famÃlia de é muita coisa. Quando a gente tem isso o que a gente faz é usar conjunto o padrão Prototype, que a gente vai ver num outro vÃdeo seguinte. A gente vai ver que esse padrão Prototype ele ajuda bastante, porque a gente cria dicionário mapeando os produtos, a gente não precisa ficar criando essas várias classes. Depois a gente vê como funciona isso. Linguagem dinâmicas como Smaltalk, Ruby e Python, onde as classes são objetos de primeira classe, então a própria classe é objeto nessas linguagens dinâmicas. A gente não precisa guardar uma instância prototÃpica desse padrão para o Prototype, a gente guarda uma referência para a classe e daà a gente usa o método new para construir as instâncias. Isso vai ficar mais claro quando você usar uma linguagem dinâmica tipo, quando você for aprender Python. Java até dá para fazer essa simplificação, mas é complicado, não fica tão, usando a parte de reflexão de Java, mas não fica tão simples quanto fica nessas linguagens dinâmicas tipo Python. E a gente pode fazer umas fábricas extensÃveis, qual é que é a ideia aqui? Normalmente, cada tipo de produto tem o seu próprio tem o seu método fábrica, crie botão, crie barra de rolagem, mas isso torna a inclusão de novos produtos, no nosso sistema complicado, como eu já falei. Então, uma solução, é usar apenas método fábrica que recebe como parâmetro por exemplo com string, o que é que precisa ser feito? Então pode ser assim, por exemplo, método make que devolve produto e ele recebe como parâmetro string thing to be made. Então você fala make button, passa o string button como parâmetro e daà ele gera o botão. Agora como é que você implementa isso lá dentro, a gente vai ver exemplos. Isso aumenta a flexibilidade, mas torna o código menos seguro porque a gente não vai ter verificação de tipo de compilador, então porque ele sempre devolve algo do tipo genérico Product. Então se o programador fizer algo errado por exemplo, ele pede para criar botão, mas ele coloca esse botão num lugar onde devia ser uma barra de rolagem o compilador não vai pegar esse erro. Então pode ser que dê algum erro tempo de execução ali quando o sistema está rodando. O que é uma coisa desagradável, mas sempre tem as vantagens e desvantagens. Toda a decisão que o arquitecto de software faz tem coisas boas e coisas ruins. Então aqui de novo, a gente diminui e simplifica porque vai ter único método make que gera todos os produtos, mas a gente perde nessa verificação de tipos pelo compilador. Vamos ver exemplo. De novo o GoF, ele tem os exemplos C ++ e Smaltalk, a gente vai ver exemplo Java. Esse é exemplo que eu peguei desse desenvolvedor do Eugen Paraschiv da Roménia é código que está no GitHub com a licença de software livre MIT e ele é exemplo de código de uma fábrica de brinquedos. Eu vou abrir aqui o meu Eclipse que a gente vai ver a fábrica de brinquedos que ele fez. Então, como é que funciona? Primeiro ele tem essa classe Abstract Factory que ele fez uma Abstract Factory bem genérica, ou seja, usando a programação genérica, generics, ele passa como parâmetro o tipo T, que vai ser o tipo de coisa que essa fábrica abstrata vai depois, quando se tornar uma fábrica concreta, que tipo de coisa é que ela vai lidar. E daà ele tem esse método fábrica que é o create, esse factory method aqui, que é o método create e você passa como parâmetro string, que diz o tipo de coisa que você quer criar. Então essa é classe abstrata super simples, com único método fábrica. E dai ele tem subclasses dessa fábrica abstrata. Primeiro então lembra, é uma fábrica de briquedos e os briquedos que ele tem no exemplo são bonequinhos de animais, que representam animais. E os animais podem ter várias cores diferentes. Então, sei lá, a gente vai ver exemplos aqui. Então como é que ele faz? A classe AnimalFactory implementa essa AbstractFactory aqui. AbstractFactory ele definiu como uma interface, não é uma classe abstrata é uma interface, então por isso é que tem o implements aqui e não extense, AbstractFactory do tipo animal. Então virou uma fábrica especÃfica para animais aqui. E daà ele tem esse método create, que é o método fábrica, recebe como parâmetro o tipo de animal que tem que ser criado. Como é que ele faz a seleção aqui? É usando if então se o tipo é dog ou seja, o que é passado como parâmetro aqui e animal type é dog, Daà que tem o new hardcoded, explicÃto, return new Dog. Daà ele instancia a classe Dog. Se é do tipo Duck é patinho, return new Duck. Caso contrário ele vai devolver null. E daà se você quiser acrescentar novos tipos de animais, basta você colocar if else aqui. Note que isso é uma apesar do padrão Fábrica estar numa boa orientação a objetos, a implementação desse método create com esse monte de if e else não é boa orientação a objetos então aqui dentro é algo que a gente poderia melhorar depois quando a gente vê o padrão Prototype, é jeito bem elegante, orientado a objetos de a gente remover esse monte de if e else daqui de dentro. Mas essa aqui é a nossa Fábrica Abstrata. Ele criou também além da Fábrica de Animais e daà até vamos ver o animal Dog, vamos ver a classe Dog aqui. A classe Dog é muito simples. Primeiro a classe Animal que é a superclasse, então deixa ver Animal.java, ela tem uma interface animal, coisa do tipo animal, ele simplesmente devolve o tipo de animal e devolve também o som que o animal faz. Então o Dog, quando você pergunta qual o tipo, ele fala Dog e quando pergunta qual é o som que ele faz, ele Barks. Ele late. Au au. Então essa classe Animal, depois tem outra implementação do Duck que é parecido na mesma linha e além dessa classe AnimalFactory ele tem uma ColorFactory que é uma fabricante de cores para as cores dos brinquedinhos. E daà é exatamente seguiu do mesmo esquema que ela fez o AnimalFactory fez o AbstractFactory, única diferença é que passa color aqui como parâmetro e as cores de novo. Se é brown, é marron, ele faz new na cor brown. Se é branco ele faz new na cor white. E é uma coisa muito simples. E daà tem aqui exemplo... E daà tem o FactoryProvider. Esse FactoryProvider, isso não faz parte do padrão mas é outra coisa interessante que ele fez. Que é o seguinte: é uma classe FactoryProvider que tem esse método GetFactory, que recebe como parâmetro que tipo de fábrica que você quer. E se você passa uma fábrica do tipo Toy, ele te devolve uma AnimalFactory. Fala "Quero uma fábrica de brinquedos" daà ele te devolve uma AnimalFactory. Se você pede uma fábrica de cores ele te devolve uma ColorFactory. Então isso aqui é como se fosse uma fábrica de fábricas. Você passa como parâmetro o tipo de fábrica que você quer e ele devolve uma fábrica daquele tipo de elemento. Uma fábrica de fábricas, de certo modo, que ele criou aqui. De novo tem aqueles if e else feios que a gente poderia resolver por exemplo usando o padrão Prototype. E daà vamos ver exemplo de uso para terminar. Como que a gente usa isso? Então tem esse método Main aqui Que é que ele faz? Primeiro ele tem essa fábrica abstrata aqui e daà ele faz o seguinte: na fábrica abstrata eu quero que você guarde ali o meu Toy. Não, desculpem, guarde o meu Toy não, você pede para o FactoryProvider criar uma fábrica, me devolver uma referência para uma fábrica de brinquedos. Daà ele guarda aqui. Daà usando essa fábrica de brinquedos, crie Dog, crie cachorrinho. E daà esse cachorrinho é guardado nessa varÃavel toy aqui. Daà de novo ele usa o FactoryProvider pela segunda vez para pegar uma fábrica de cores e agora usando essa fábrica de cores me devolva uma referência para a cor marron, brown. E daà sim ele imprime esse resultado aqui. Esse resultado é o quê? É A esse é o artigo 1, na linha inglesa, toy.getType, então o tipo do brinquedo portanto vai ser cachorro. Então falando, cachorro, wtih e daà vai dizer color.getColor provavelmente vai devolver o nome da color com a tal cor. E ele faz, esse brinquedo faz este som. Então se eu mandar executar, vou mandar executar aqui o código, o brinquedo faz este som. Ele manda imprimri. Imprimiu aqui, A Dog with brown color barks. O toy.getType devolveu o cachorro, colo.getColor devolveu brown e o toy. makeSound respondeu Barks. Então cachorro de cor marron, late. Exemplinho bem simplesinho ultra simples do uso do padrão Fábrica Abstrata. Espero que vocês tenham achado esse exemplo interessante. Então é isso, lembro que a gente usa o padrão Fábrica Abstrata quando a gente quer desacoplar os tipos especÃficos de elementos que são criados do cliente que usa o código. Então new e o nome da classe a gente deixa escondido do cliente de forma que o cliente possa trabalhar com diferentes famÃlias de objetos diferentes momentos. E o Fábrica Abstrata ajuda a garantir a consistência dessas famÃlia para não misturar objetos de famÃlias diferentes, objetos do Velho oeste e mistura com objetos do espaço sideral. Se a gente não tem esse famÃlias, o objeto é único, tipo de objeto que tem subtipos, daà a gente não precisa usar Fábrica Abstrata, basta método fábrica. Então espero que vocês tenham gostado e até ao próximo padrão. Eu recomendo olhar o padrão Prototype porque vai ajudar a gente a tornar a nossa Fábrica Abstrata mais elegante.