Design Patterns ABSTRACT FACTORY EMERSON BARROS DE MENESES 1
Breve Históric Sbre Design Patterns A rigem ds Design Patterns (Padrões de Desenh u ainda Padrões de Prjet) vem d trabalh de um arquitet chamad Christpher Alexander, n final da década de 70. Ele escreveu dis livrs, inicialmente, A Pattern Language [Alex77] e A Timeless Way f Building [Alex79], ns quais ele exemplificava us e descrevia seu racicíni para dcumentar s padrões. Em 1995, um grup de quatr prfissinais escreveu e lançu livr "Design Patterns: Elements f Reusable Object-Oriented Sftware" [Gamma95] e traduzid para Padrões de Prjet: sluções reutilizáveis de sftware rientad a bjets [2000], um catálg cm 23 padrões de desenh (design patterns). Os autres: Erich Gamma, Richard Helm, Ralph Jhnsn, and Jhn Vlissides, ficaram mais cnhecids cm A Gangue ds Quatr (Gang Of Fur u GF), cnsiderads s maires entusiastas ds Design Patterns. Cuj mesm livr fi utilizad na criaçã deste trabalh. Breve resum sbre que é um Design Patterns? Os Design Patterns sã padrões de classes e de relacinaments entre as mesmas que aparecem de frma freqüente em prjets de sftware. Tais padrões sã categrizads para atender a sluções específicas. Sua utilizaçã é uma atividade que simplifica a reutilizaçã de sftware. Os padrões aparecem em situações especiais dentr de um sistema cm descrições de bjets e classes cmunicantes que sã custmizadas um cntext particular. Este descreve uma sluçã cmprvada para um prblema, sã mais abstrats, menres e mens específics que framewrks que pr sua vez é um cnjunt de classes que pde ser utilizad para um tip específic de prjet de sftware (análise de dmíni, bibliteca de reus). Uma primeira visualizaçã (entendiment) crrespnde à tríade mdel, vista e cntrladr (MVC). Prcuram estabelecer uma distinçã rígida entre estes elements de md a trná-ls independentes. Ou seja, mdel, vista e cntrladr pdem ser mdificads de frma independente (desacplament). Patterns sã dispsitivs que permitem que s prgramas cmpartilhem cnheciment sbre seu desenh. Quand prgramams, encntrams muits prblemas 2
que crrem, crreram e irã crrer nvamente. A questã que ns perguntams agra é cm nós vams slucinar este prblema desta vez? Dcumentar um padrã (pattern) é uma maneira de pder reusar e pssivelmente cmpartilhar infrmaçã que aprendeu sbre a melhr maneira de se reslver um prblema de desenh de sftware. O catálg de padrões d GF (Gang Of Fur), cm dit, cntém 23 padrões e está, basicamente, dividid em três seções: Creatinal (Criacinal), Structural (Estrutural), Behaviral (Cmprtamental). Neste trabalh irems elencar pnts referentes a Padrã Criacinal Abstract Factry. 3
Abstract Factry (Design Patterns Creatinal) Intrduçã Padrã que cria um cnjunt de famílias de bjets cm características cmuns. A esclha pela adçã de uma determinada família e a cnseqüente instanciaçã ds bjets pde ser definida em temp de execuçã. Objetiv Prver uma interface para criar uma família de bjets relacinads u dependentes Escp sem especificar suas classes cncretas. De Objet Prpósit De criaçã Também chamad de Kit Resum Parece semelhante a padrã Factry Methd, mas Em vez d cliente (que quer criar bjets sem saber as classes exatas) chamar um métd de criaçã (Factry Methd, escp de Classe), ele de 4
alguma frma pssui um bjet (uma Abstract Factry) e usa este bjet para chamar s métds de criaçã Onde Factry Methd quer que vcê seja diferente (via herança) para criar bjets diferentes, Abstract Factry quer que vcê tenha alg diferente Se ele pssuir uma referência a uma Abstract Factry diferente, tda a criaçã será diferente O fat de tds s métds de criaçã estarem na mesma subclasse de uma Abstract Factry permite satisfazer a restriçã de criar apenas bjets relacinads u dependentes Exempl: lk-and-feel de GUIs Para lk-and-feel diferentes (Mtif, Windws, Mac, Presentatin Manager, etc.) tems frmas diferentes de manipular janelas, scrll bars, menus, etc. Para criar uma aplicaçã cm GUI que suprte qualquer lk-and-feel, precisams ter uma frma simples de criar bjets (relacinads) de uma mesma família Os bjets sã dependentes prque nã pde criar uma janela estil Windws e um menu estil Mtif Java já reslveu este prblema internamente n package awt usand Abstract Factry e nã precisa se precupar cm iss Prém, pderia estar usand C++ e precisaria cuidar diss pessalmente Uma classe (abstrata) (u interface, em Java) "Abstract Factry" define uma interface para criar cada tip de bjet básic (widgets n linguajar GUI) Também tem uma classe abstrata para cada tip de widget (windw, scrll bar, menu,...) Há classes cncretas para implementar cada widget em cada platafrma (lk-andfeel) Clientes chamam a Abstract Factry para criar bjets Uma Cncrete Factry cria s bjets cncrets aprpriads Ver diagrama de classes abaix: 5
6
Mais detalhadamente seria: Quand usar padrã Abstract Factry? Quand um sistema deve ser independente de cm seus prduts sã criads, cmpsts e representads Quand um sistema deve ser cnfigurad cm uma entre várias famílias de prduts Quand uma família de prduts relacinads fi prjetada para us cnjunt e vcê deve implementar essa restriçã Quand deseja frnecer uma bibliteca de classes e quer revelar sua interface e nã sua implementaçã 7
Nã permita prtant que bjets sejam diretamente criads cm new Estrutura genérica 8
Mais detalhadamente seria: Participantes FactryIF (WidgetFactryIF) Define uma interface para as perações que criam bjets cm prduts abstrats FactryAbstrata (WidgetFactry) Pssível classe abstrata para fatrar códig cmum às FactryCncretas FactryCncreta (MtifWidgetFactry, WindwsWidgetFactry) Implementa as perações para criar bjets para prduts cncrets 9
PrdutXIF (WindwIF, ScrllBarIF) Define uma interface para bjets de um tip PrdutAbstrat (Windw, ScrllBar) Pssível classe abstrata para fatrar códig cmum as PrdutsCncrets PrdutCncret (MtifWindw, MtifScrllBar) Cliente Define um bjet prdut a ser criad pela FactryCncreta crrespndente Implementa a interface de PrdutAbstrat Usa apenas interfaces definidas pr FactryIF e PrdutXIF Clabrações entre bjets Nrmalmente uma única instância de uma classe FactryCncreta é criada em temp de execuçã Essa FactryCncreta cria bjets tend uma implementaçã particular Para criar prduts diferentes, clientes devem usar uma FactryCncreta diferente FactryAbstrata depende de suas subclasses FactryCncreta para criar bjets de prduts Cnsequências d us d padrã Abstract Factry O padrã isla classes cncretas Uma factry encapsula a respnsabilidade e prcess de criaçã de bjets de prduts Isla clientes das classes de implementaçã O cliente manipula instâncias através de suas interfaces abstratas Facilita câmbi de famílias de prduts A classe da FactryCncreta só aparece em um lugar: nde ela é instanciada Uma mudança numa única linha de códig pde ser suficiente para mudar a FactryCncreta que a aplicaçã usa A família inteira de prduts muda de uma vez Prmve a cnsistência entre prduts 10
Prduts de uma determinada família devem funcinar cnjuntamente e nã misturads cm prduts de utra família O padrã permite implementar esta restriçã cm facilidade D lad negativ: dar suprte a nvs tips de prduts é difícil O mtiv é que a FactryAbstrata fixa cnjunt de prduts que pdem ser criads Dar suprte a mais prduts frça a extensã da interface da factry que envlve mudanças na FactryAbstrata e em tdas suas subclasses FactryCncreta Cnsiderações de implementaçã Factry cm padrã Singletn Uma aplicaçã nrmalmente só precisa de uma única instância de uma FactryCncreta pr família de prduts O padrã Singletn ajuda a cntrlar a instância única Criaçã ds prduts A FactryIF apenas define a interface de criaçã Quem cria s bjets sã as FactryCncreta Tais subclasses sã freqüentemente implementadas usand padrã Factry Methd Uma FactryCncreta faz verride d Factry Methd de cada prdut Exempl de códig: criaçã de labirints Tds s Factry Methds da classe Jg entram na factry abstrata FactryDeLabirint Também pssuem um default, que significa que FactryDeLabirint também é uma factry cncreta public interface FactryDeLabirintIF { public LabirintIF crialabirint(); public SalaIF criasala(int númerdasala); 11
public ParedeIF criaparede() { public PrtaIF criaprta(salaif sala1, SalaIF sala2) { public class FactryDeLabirint implements FactryDeLabirintIF { private static FactryDeLabirintIF instânciaúnica = null; private FactryDeLabirint() { public static FactryDeLabirintIF getinstance(string tip) { if(instânciaúnica == null) { if(tip.equals("perigs")) { instânciaúnica = new FactryDeLabirintPerigs(); else if(tip.equals("encantad")) { instânciaúnica = new FactryDeLabirintEncantad(); else { instânciaúnica = new FactryDeLabirint(); return instânciaúnica; // Factry Methds // Tem default para as Factry Methds public LabirintIF crialabirint() { return new Labirint(); public SalaIF criasala(int númerdasala) { return new Sala(númerDaSala); public ParedeIF criaparede() { return new Parede(); public PrtaIF criaprta(salaif sala1, SalaIF sala2) { return new Prta(sala1, sala2); 12
mntalabirint recebe um FactryDeLabirintIF cm parâmetr e cria um labirint public class Jg implements JgIF { // Essa funçã nã tem new: ela usa uma Abstract Factry public LabirintIF mntalabirint(factrydelabirintif factry) { LabirintIF umlabirint = factry.crialabirint(); SalaIF sala1 = factry.criasala(1); SalaIF sala2 = factry.criasala(2); PrtaIF aprta = factry.criaprta(sala1, sala2); umlabirint.adicinasala(sala1); umlabirint.adicinasala(sala2); sala1.setvizinh(norte, factry.criaparede()); sala1.setvizinh(leste, aprta); sala1.setvizinh(sul, factry.criaparede()); sala1.setvizinh(oeste, factry.criaparede()); sala2.setvizinh(norte, factry.criaparede()); sala2.setvizinh(leste, factry.criaparede()); sala2.setvizinh(sul, factry.criaparede()); sala2.setvizinh(oeste, aprta); return umlabirint; Para criar um labirint encantad, fi criad uma factry cncreta cm subclasse de FactryDeLabirint public class FactryDeLabirintEncantad extends FactryDeLabirint { public SalaIF criasala(int númerdasala) { return new salaencantada(númerdasala, jgaencantament()); public PrtaIF criaprta(salaif sala1, SalaIF sala2) { return new prtaprecisanddeencantament(sala1, sala2); prtected EncantamentIF jgaencantament() {... 13
Para criar um labirint perigs, criams uma utra factry cncreta cm subclasse de FactryDeLabirint public class FactryDeLabirintPerigs extends FactryDeLabirint { public ParedeIF criaparede() { return new parededestruível(); public SalaIF criasala(int númerdasala) { return new salacmbmba(númerdasala); Finalmente, é pssível jgar: JgIF umjg = new Jg(); FactryDeLabirint factry = FactryDeLabirint.getInstance("perigs"); jg.mntalabirint(factry); 14
Questões gerais de padrões de criaçã Ajudam a deixar sistema independente de cm seus bjets sã criads, cmpsts e representads Sã dis tips: Padrões de criaçã via classes Usam herança para variar a classe que é instanciada Exempl: Factry Methd Padrões de criaçã via bjets 15
Delegam a instanciaçã para utr bjet Exempl: Abstract Factry Cmpsiçã é usada mais que herança para estender funcinalidade e padrões de criaçã ajudam a lidar cm a cmplexidade de criar cmprtaments Em vez de cdificar um cmprtament estaticamente, definims pequens cmprtaments padrã e usams cmpsiçã para definir cmprtaments mais cmplexs Iss significa que instanciar um bjet cm um cmprtament particular requer mais d que simplesmente instanciar uma classe Eles escndem cm instâncias das classes cncretas sã criadas e juntadas para gerar "cmprtaments" (que pdem envlver váris bjets cmpsts) Os padrões mstrads aqui mstram cm encapsular as cisas de frma a simplificar prblema de instanciaçã Os padrões de criaçã discutem temas recrrentes: Eles encapsulam cnheciment das classes cncretas que sã instanciadas Lembre que preferims ns "amarrar" a interfaces (via interface u classes abstratas) d que a classes cncretas Iss prmve a flexibilidade de mudança (das classes cncretas que sã instanciadas) 16
Bibligrafia: http://pt.wikipedia.rg/wiki/abstract_factry http://www.guj.cm.br/articles/137 http://www.dsc.ufcg.edu.br/~jacques/curss/map/html/pat/abstractfactry.htm GAMMA, Erich; HELM, Richard; JOHNSON, Ralph; VLISSIDES, Jhn. Padrões de Prjet: sluções reutilizáveis de sftware rientad a bjets. Ed. 1. Bkman, 2000. ISBN 9788573076103. 17
Design Patterns - ABSTRACT FACTORY Pr Emersn Barrs de Meneses 18