# Prototype

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

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.

### Código

Este código, escrito na linguagem Java, mostra a implementação do diagrama mostrado acima.
Observação: Na linguagem Java, a interface Cloneable não possui métodos e é utilizada apenas para indicar que o método Object.clone pode realizar uma cópia, atributo por atributo, das instâncias de uma classe.
Neste exemplo, a implementação da cópia da instância é delegada ao método clone da super classe Object (A classe raiz da hierarquia de classes da linguagem Java). Se fosse necessário, as classes Documento, ASCII ou PDF implementariam esse método para refletir algum comportamento específico.