O Factory tem como principal objetivo a criação de objetos, como seu próprio nome diz, fábrica.
Com esse padrão é possível que eu fabrique minhas instâncias de forma centralizada, de forma que quando eu precisar alterar a forma que esses objeto são instanciados eu altero em apenas um só lugar.
Vamos ver isso na prática com um exemplo bem simples e de fácil entendimento.
Vamos imaginar o seguinte cenário: temos uma classe Forma e teremos suas subclasses Triangulo e Circulo, nossa classe forma que ficará encarregada de instanciar e retornar um Circulo ou Triangulo de acordo com o que foi solicidado.
Abaixo nossa classe Forma:
abstract public class Forma {
abstract public void calcularArea();
public static Forma getForma(int [] atributos){
//circulo
if(atributos.length == 1){
return new Circulo(atributos[0]);
}
//triangulo
if(atributos.length==2){
return new Triangulo(atributos[0], atributos[1]);
}
//caso a forma solicitada não exista
return null;
}
}
Vemos acima na nossa classe Forma que temos um método abstrato calcularArea() e um método estático getForma(int[] atributos) esse método é que é responsável por verificar que tipo de instância a classe cliente precisa, que no nosso caso é verificado de acordo com a quantidade de parâmetros passadas no array.
Normalmente uma classe Factory retorna apenas objetos de suas subclasses.
Abaixo nossas classes Circulo e Triangulo:
public class Circulo extends Forma {
private int raio;
public Circulo(int raio) {
this.raio = raio;
}
public String toString() {
return "Circulo";
}
@Override
public void calcularArea() {
//PI * raio^2
System.out.println(Math.PI*Math.pow(this.raio, 2));
}
}
public class Triangulo extends Forma {
private int base;
private int altura;
public Triangulo(int b, int a) {
this.base = b;
this.altura = a;
}
public String toString() {
return "Triângulo";
}
@Override
public void calcularArea() {
// (base * altura)/2
System.out.println((this.base*this.altura)/2);
}
}
Acima nas nossas classes Circulo e Triangulo apenas reescrevemos o método toString() da classe Object para retornarmos o tipo de objeto e reimplementamos o o método calcularArea() herdado da nossa classe abstrata Forma, observe que a reimplementação do método é feita de acordo com cada tipo de objeto em suas respectivas classes.
Agora vamos escrever nossa classe cliente que utilizará dos serviços da nossa classe Forma para criar seus objetos.
public class Cliente {
public static void main(String[] args){
Forma forma = Forma.getForma(new int[]{4});//será retornado um Circulo
forma.calcularArea();//será invocado o método calcularArea de Circulo
Forma forma2 = Forma.getForma(new int[]{8,9});//será retornado um Triangulo
forma2.calcularArea();//será invocado o método calcularArea de Triangulo
}
}
Na nossa classe Cliente criamos dois objetos do tipo forma, no primeiro obtemos uma instância de Forma através do método estático getForma(int[] att) passando um array contendo uma posição, desta forma na nossa classe forma será verificado dentro do método e retornado um objeto Forma do tipo Circulo.
Após isso invocamos o método calcularArea() do objeto recem criado, no qual será calculado a área de um Circulo.
Na segunda instanciação do objeto forma na nossa classe Cliente foi feita da mesma forma que a primeira, só que desta vez passamos um array de duas posições para o nosso método getForma(int[] att) que por sua vez retornará um objeto Forma do tipo Triângulo.
Após isso invocamos o método calcularArea() do objeto recem criado, no qual será calculado a área de um Triangulo.
Bom é isso, espero que tenha ficado bem claro, qualquer dúvida estou a disposição.
Obrigado.
