Tópicos Avançados em Linguagem de Programação Padrões de Projeto Pattern Prof. Alexandre Vidal DEINF-UFMA Classificação: Propósito: Criacional / Escopo: Objetos Padrão de Construção (intenção/metsker) Intenção: separar a criação de um objeto complexo de sua representação de modo que o mesmo processo de construção possa criar diferentes representações. Ciência da Computação Motivação: Motivação: um leitor para documentos RTF (Rich Text Format) deve poder converter o documento para diferentes formatos o número de formatos possíveis é aberto portanto, é preciso facilitar a adição de uma nova conversão sem modificar o leitor uma solução é configurar o RTFreader com um conversor, para converter e representar o texto em um novo formato subclasses do conversor são especializadas em diferentes conversões e formatos no padrão : o conversor é chamado builder o leitor é chamado director o leitor é configurado com o builder o padrão separa o algoritmo para interpretação do formato textual (no leitor)... do algoritmo que converte o formato lido em outro formato, e que cria, compõe e representa esse novo formato (no builder)
Motivação: Aplicabilidade ( quando usar o padrão ) : quando o algoritmo para criação de um objeto complexo deve ser independente das partes que o compõem e de como elas são montadas o processo de construção deve permitir diferentes representações para o objeto construído Estrutura Estrutura
Participantes : especifica uma interface abstrata para criação de partes de um objeto-produto Concrete: implementa a interface do para construir e montar partes do produto define e mantém a representação que cria fornece interface para recuperação do produto Participantes Director: constrói um objeto usando a interface do Product: representa o objeto complexo em construção inclui classes que que definem as partes constituintes, inclusive as interfaces para a montagem das partes no resultado final Colaborações Conseqüências o cliente cria o objeto Director e o configura com o objeto desejado Director notifica o construtor sempre que uma parte do produto deve ser construída o cliente recupera o produto do construtor permite variar a representação interna de um produto isola o código para construção e representação oferece controle mais fino sobre o processo de construção
Implementação (aspectos) interface de montagem e construção: um modelo que apenas agrega os novos construtos ao produto é, em geral, suficiente, mas às vezes é necessário acessar partes já agregadas ao produto porque não classes abstratas para produtos? em geral, os produtos têm representações tão diferentes, que não há vantagens em ter uma superclasse comum Implementação (aspectos) Métodos vazios como default em. em C++, métodos build intencionalmente não são declarados virtuais puros antes, são definidos como métodos vazios os clientes sobrescrevem apenas as operações que lhes interessam Exemplo de Código class Maze { public: virtual void BuildMaze() { } virtual void BuildRoom(int room) { } virtual void BuildDoor(int roomfrom, int roomto) { } virtual Maze* GetMaze() { return 0; } protected: Maze(); } podemos alterar a função CreateMaze para receber o builder como um parâmetro: Maze* MazeGame::CreateMaze (Maze& builder) { builder.buildmaze(); builder.buildroom(1); builder.buildroom(2); builder.builddoor(1, 2); return builder.getmaze(); }
podemos reusar Maze para construir diferentes tipos de labirintos. A operação CreateComplexMaze é um exemplo: Maze* MazeGame::CreateComplexMaze (Maze& builder) { builder.buildroom(1); //... builder.buildroom(1001); return builder.getmaze(); } class StandardMaze : public Maze { public: StandardMaze(); virtual void BuildMaze(); virtual void BuildRoom(int); virtual void BuildDoor(int, int); virtual Maze* GetMaze(); private: Direction CommonWall(Room*, Room*); Maze* _currentmaze; }; void StandardMaze::BuildRoom (int n) { if (!_currentmaze->roomno(n)) { Room* room = new Room(n); _currentmaze->addroom(room); room->setside(north, new Wall); room->setside(south, new Wall); room->setside(east, new Wall); room->setside(west, new Wall); } void StandardMaze::BuildDoor (int n1, int n2) { Room* r1 = _currentmaze->roomno(n1); Room* r2 = _currentmaze->roomno(n2); Door* d = new Door(r1, r2); r1->setside(commonwall(r1,r2), d); r2->setside(commonwall(r2,r1), d); } }
Clientes podem agora usar CreateMaze junto com StandardMaze para criar um labirinto: Maze* maze; MazeGame game; StandardMaze builder; game.createmaze(builder); maze = builder.getmaze(); Usos conhecidos ver página 111 no GoF (traduzido); Padrões Relacionados Abstract Factory ênfase na construção de família de produtos (simples ou complexos), enquanto constrói um objeto complexo passo a passo; O produto é devolvido imediatamente, enquanto devolve o produto como um passo final. Composite é freqüentemente construído pelo.