009 – Padrão de Projeto PROTOTYPE – Padrão GoF de Criação – Curso de Design Patterns
Playlist do Curso de Padrão de Projeto de Software (Design Patterns)
Prototype, na ciência da computação, é um padrão de projeto de software (design pattern, em inglês). Criacional que permite a criação de novos objetos a partir de um modelo original ou protótipo que é clonado.
Este padrão pode ser utilizado para:
Evitar que as subclasses que criam objetos funcionem como o padrão abstract factory;
Evitar criar um novo objeto utilizando a palavra new, o que diminui o custo de memória.
Basicamente, ao em vez de o cliente implementar um código que utiliza o operador new, este utiliza o método clone() presente no protótipo e o método de uma fábrica(Factory Method ou Abstratct Factory) que fica encarregada de clonar o novo objeto.
Estrutura
Diagrama UML da estrutura do padrão Prototype
O padrão Prototype, da forma como foi descrito no livro Design Patterns: Elements of Reusable Object-Oriented Software, contém os seguintes elementos:
prototype — uma classe que declara uma interface para objetos capazes de clonar a si mesmo.
prototype concreto — implementação de um prototype;
cliente — cria um novo objeto através de um prototype que é capaz de clonar a si mesmo.
Efetivamente, cada objeto é, ele próprio, um factory especializado em construir objetos iguais a si mesmo. O padrão Prototype é utilizado frequentemente em linguagens estaticamente tipadas como C++ e Java, e menos frequentemente utilizadas em linguagens dinamicamente tipadas como Smalltalk.
O padrão Prototype exige a implementação de uma operação de clonagem em cada uma das classes concretas do protótipo. Esta tarefa pode ser inconveniente, no caso do reaproveitamento de classes preexistentes que não possuem tal operação, ou mesmo complexa, se for considerada a possibilidade de existirem referências circulares nos atributos de um objeto (um objeto possui um atributo que referencia um objeto que, por sua vez, referencia o objeto original).
Utilização
O padrão Prototype é aplicado quando existe a necessidade de clonar, literalmente, um objeto. Ou seja, quando a aplicação precisa criar cópias exatas de algum objeto em tempo de execução este padrão é altamente recomendado. Este padrão pode ser utilizado em sistemas que precisam ser independentes da forma como os seus componentes são criados, compostos e representados. O padrão Prototype pode ser útil em sistemas com as seguintes características:
sistemas que utilizam classes definidas em tempo de execução;
sistemas que utilizam o padrão Abstract Factory para criação de objetos. Neste caso, a hierarquia de classes pode se tornar muito complexa e o padrão Prototype pode ser uma alternativa mais simples, por realizar a mesma tarefa com um número reduzido de classes;
sistemas que possuem componentes cujo estado inicial possui poucas variações e onde é conveniente disponibilizar um conjunto preestabelecido de protótipos que dão origem aos objetos que compõem o sistema.
Algumas vezes, padrões criacionais podem ser “competidores”: Existem casos em que o Prototype ou Abstract Factory podem ser utilizados apropriadamente. Em outros, eles são complementares: Um Abstract Factory pode conter um set de Prototypes no qual clona e retorna o produto de objetos.
Muitos Designers começam utilizando o Factory Method, pois seu uso é menos complicado, mas então evoluem para Abstract Factory, Prototype ou Builder, que são mais flexíveis porém mais complexos. E é neste ponto em que o Factory Method e Prototype divergem: O primeiro requer subclasses, mas não precisa ser inicializado. O segundo, não necessita de subclasses porém precisa ser inicializado.
Quando utiliza o framework Spring, por exemplo, um desenvolvedor pode configurar um JavaBean como “prototype”. Esta configuração faz com que cada uma das referências a um JavaBean aponte para uma instância diferente. O comportamento padrão, ou singleton, define que todas as referências a um JavaBean apontem para a mesma instância de uma classe.
Uma das principais vantagens de sua utilização é quando a inicialização de um objeto pode se tornar custosa, e você quer fazer algumas pequenas variações ao inicializar. Nesse contexto, o Prototype pode então evitar a criação “do zero” de novos objetos.
Exemplo
Neste exemplo é mostrado uma hierarquia de classes representando documentos de formato ASCII e PDF que são criados através da classe Cliente. A partir de duas instâncias prototípicas, ascii e pdf, o método criarDocumento cria clones de documentos de acordo com o tipo desejado. A tarefa de realizar a criação da instância é implementada na classe Documento e herdada por suas classes filhas, ASCII e PDF.