Projeto de Sistemas de Software Abstract Factory Padrões de projeto Bruno Freitas Gadelha Setembro, 2008 1 Abstract Factory Propósito Motivação Aplicabilidade Estrutura Participantes Colaborações Consequências Exemplo 2 Abstract Factory Propósito Prover uma interface para criar uma família de objetos relacionados ou dependentes sem especificar suas classes concretas 3 Abstract Factory Motivação Montadoras Diferentes modelos Diferentes acessórios Gerador de carros de documentos Diferentes documentos (textos, planilhas, apresentacoes) Diferentes estilos de documentos (cartas de recomendação, curriculos, etc.) 4 Abstract Factory Aplicabilidade Um sistema deve ser independente de como seus produtos sao criados, compostos e representados Um sistema deve ser configurado como um de múltiplas famílias de produtos 5 Abstract Factory Estrutura 6 Abstract Factory Participantes AbstractFactory: Declara uma interface para a criação de objetos abstratos. ConcreteFactory: Implementa as operações que criam objetos concretos. AbstractProduct: Declara uma interface para um tipo de objeto. ConcreteProduct: Define um objeto a ser criado pela fábrica concreta correspondente e implementa a interface de AbstractProduct. Client: Utiliza somente as interfaces declaradas pelas classes AbstractFactory e AbstractProduct. 7 Abstract Factory Colaborações Normalmente uma única instância de uma classe FactoryConcreta é criada em tempo de execução. Essa FactoryConcreta cria objetos tendo uma implementação particular. Para criar produtos diferentes, clientes devem usar uma FactoryConcreta diferente. FactoryAbstrata depende de suas subclasses FactoryConcreta para criar objetos de produtos 8 Abstract Factory Consequências O padrão isola classes concretas Uma factory encapsula a responsabilidade e o processo de criação de objetos de produtos Isola clientes das classes de implementação O cliente manipula instâncias através de suas interfaces abstratas Facilita o câmbio de famílias de produtos A classe da FactoryConcreta só aparece em um lugar: onde ela é instanciada Uma mudança numa única linha de código pode ser suficiente para mudar a FactoryConcreta que a aplicação usa A família inteira de produtos muda de uma vez 9 Abstract Factory Consequências Promove a consistência entre produtos Produtos de uma determinada família devem funcionar conjuntamente e não misturados com produtos de outra família O padrão permite implementar esta restrição com facilidade Do lado negativo: dar suporte a novos tipos de produtos é difícil O motivo é que a FactoryAbstrata fixa o conjunto de produtos que podem ser criados Dar suporte a mais produtos força a extensão da interface da factory o que envolve mudanças na FactoryAbstrata e em todas suas subclasses FactoryConcreta 10 Abstract Factory Exemplo public abstract class Document { protected String content; public String getContent() { return content;} public abstract String getTemplate(); public abstract String getType(); } ProdutoAbstrato ProdutoA1 public class SimpleLetterDocument extends Document{ public String getTemplate(){ // conteúdo para retornar o template deste tipo de documento} public String getType(){ return “Simple Letter”; } } 11 Abstract Factory Exemplo ProdutoA2 public class ProfessionalLetterDocument extends Document{ public String getTemplate(){ // conteúdo para retornar o template deste tipo de documento } public String getType(){ return “Pro Letter”;} } ProdutoB1 public class SimpleSpreadSheetDocument extends Document{ public String getTemplate(){ … } public String getType(){ return “Simple Spreadsheet”;} } 12 Abstract Factory Exemplo public class FancySpreadSheetDocument extends Document{ public String getTemplate(){…} public String getType() { return “Fancy Spreadsheet”; } } public class LetterFactory{ public static Document getLetter(String style){ if(”simple”.equals(style)) { return new SimpleLetterDocument(); } if(”pro”.equals(style)) { return new ProfessionalLetterDocument();} else return null; } } ProdutoB2 ConcreteFactory p/ cartas 13 Abstract Factory Exemplo public class SpreadSheetFactory{ public static Document getSpreadSheet(String style){ if(”simple”.equals(style)) {return new SimpleSpreadSheetDocument();} if(”fancy”.equals(style)) {return new FancyLetterDocument();} else return null; } } public class DocumentFactory{ public Document getDocument(String type, String style){ if(”letter”.equals(type)) {return LetterFactory.getLetter(style);} if(”spreadsheet”.equals(type)) {return SpreadSheetFactory.getSpreadSheet(style);} } } ConcreteFactory p/ planilhas AbstractFactory 14 Abstract Factory Exemplo Client public class Cliente{ public static void main(String[] args){ Document letter1 = DocumentFactory.getDocument(”letter”, “simple”); Document letter2 = DocumentFactory.getDocument(”letter”, “pro”); Document sp1 = DocumentFactory.getDocument(”spreadsheet”, “simple”); Document sp2 = DocumentFactory.getDocument(”spreadsheet”, “pro”); System.out.println(letter1.getType()); // Simple Letter System.out.println(letter2.getType()); // Pro Letter System.out.println(sp1.getType()); // Simple Spreadsheet System.out.println(sp2.getType()); // Fancy Spreadsheet } } 15