Design Patterns Catalog

Simplificando o que não é complicado

Prototype

O propósito do design pattern Prototype é definir tipos de objetos que podem ser criados a partir de outros objetos que servem como modelo ou, como diz o nome, protótipos.

Um bom exemplo do uso desse pattern seria na construção de um jogo de naves espaciais. Todas as naves do jogo têm operações comuns, como calcular as características do próximo movimento a ser realizado. Para isso podemos imaginar que essas naves são representadas por uma classe Ship que possui um método getNextMove, com a função de retornar um bean com a direção e a velocidade do próximo movimento. Além disso devemos notar que o jogo possui vários tipos de naves, e que várias naves de cada tipo serão instanciadas no transcorrer do jogo.

Nesse ponto devemos tomar a decisão de como criar cada instância de um Ship. Uma solução natural seria utilizar subclasses de Ship que implementariam um comportamento diferente para cada tipo de nave. Essa não é, porém, a melhor solução pois podemos ter uma grande número de subclasses para simular diferentes comportamentos, onde poderíamos simplesmente ter diferentes valores para os atributos de uma mesma classe.

A maneira de resolver esse problema é criar templates (ou protótipos como diz o nome do design pattern) de tipos de naves, ou seja, uma instância de Ship para cada tipo de nave existente com as suas características pré-configuradas nos seus atributos (dentre esses atributos podemos imaginar o bitmap utilizado para desenhar a nave, a quantidade de tiros que ela pode suportar e uma referência a uma classe que implemente a lógica que ela utiliza para calcular o próximo movimento). No momento de instanciar uma nova nave, ao invés de recorrermos ao artifício de usar uma subclasse podemos simplesmente clonar uma instância de Ship existente..

A maneira tradicional de utilizar esse patterns é prover um método clone na classe Ship mas também podemos utilizar uma classe utilitária capaz de clonar uma instância de um objeto.

Abaixo uma exemplo do que seria a implementação da classe Ship



	public class Ship {
		// atributos de ship
		private int vx;
		private int vy;
		private Bitmap bitmap;
		// classe que implementa o comportamento
		// da nave
		private ShipBehaviour behaviour;
		(...)

		public Move getNextMove() {
			return this.behaviour->getNextMove();
		}

		(...)
	}

A criação do pool de ships que servirá de template:


	Map prototypes = new HashMap();

	Ship ship = new Ship(vx, vy, bitmap, randomBehaviour);
	prototypes.insert("type1", ship);

	Ship ship = new Ship(vx + 1, vy + 2, bitmap, randomBehaviour);
	prototypes.insert("type2", ship);


Finalmente, o momento em que precisamos instanciar um Ship:


	Ship newShip = ClassUtils.clone(prototypes.get(typeName), Ship.class);