Archive for category Padrões de Projeto
Factory
Posted by Diego Ferreira da Silva in Padrões de Projeto on 1 de maio de 2009
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.
Template Method
Posted by Diego Ferreira da Silva in Padrões de Projeto on 4 de abril de 2009
A principal funcionalidade deste padrão de projeto é criar métodos genéricos e passar a responsabilidade de implementação as subclasses ou desenvolver métodos genéricos e alguma parte ou funcionalidade deste método possa ser feito nas subclasses.
Vamor fazer um exemplo prático para melhor entendermos:
Varmos criar uma classe conforme abaixo:
abstract public class Operacao {
abstract int handleEfetuarOperacao(int valor1,int valor2);
public void efetuarOperacao(int valor1, int valor2){
int resultado = handleEfetuarOperacao(valor1, valor2);
System.out.println("O resultado é: "+ resultado);
}
}
No código acima criamos uma classe abstrata que possui o método abstrato handleEfetuarOperacao(int valor1, valor2) que as classes filhas de Operacao serão obrigadas a implementar e possuimos também nosso método efetuarOperacao(int valor1, int valor2), que utiliza dos serviços de handleEfetuarOperacao que será implementado pelas classes filhas.
Vamos criar mais uma classe:
public class Soma extends Operacao {
@Override
public int handleEfetuarOperacao(int valor1, int valor2) {
return valor1 + valor2;
}
}
Observe que na classe acima herdamos de Operacao, portanto reimplementamos o método handleEfetuarOperacao devolvendo a soma dos valores passados por parâmetro.
Vamos agora fazer outra classe:
public class Subtracao extends Operacao {
@Override
public int handleEfetuarOperacao(int valor1, int valor2) {
return valor1 - valor2;
}
}
Na classe acima também herdamos de Operacao, portanto reimplementamos o método handleEfetuarOperacao
mas desta vez devolvendo a subtração dos parâmetros.
Vamos agora fazer uma classe que utilizará estes métodos:
public class Cliente {
public static void main(String[] args) {
Operacao op = new Soma();
Operacao op2 = new Subtracao();
op.efetuarOperacao(10, 4);
op2.efetuarOperacao(10, 4);
}
}
Na classe acima criamos dois objetos Operacao um Soma e outro Subtracao e em ambos chamamos o método efetuarOperacao(10,4) passando os mesmos valores nas duas chamadas, porém a primeira chamada irá invocar o método handleEfetuarOperacao da classe Soma e o segundo irá chamar o da classe Subtracao.
Estes serão os resultados obtidos:
O resultado é: 14
O resultado é: 6
Ok, finalizamos este post aqui.
abraço.
Singleton
Posted by Diego Ferreira da Silva in Padrões de Projeto on 28 de março de 2009
Olá pessoal!
Vamos falar hoje sobre o padrão de projeto Singleton.
Para melhor entendermos vamos imaginar que temos um sistema que necessita estabelecer conexões em diversos instantes do seu funcionamento com o banco de dados, e dependendo to tamanho do nosso sistema pode ser que ele solicite centenas de conexões com o banco de dados a cada minuto, não seria viável a nível de performance que a cada solicitação desta fosse criada uma nova conexão com o banco de dados, é ai que vamos utilizar o padrão de projetos Singleton, é claro que ele pode ser utilizado em diversos outros cenários, mas no nosso caso vamos exemplificar através deste pois o mesmo é bem didático.
O papel do Singleton é fazer com que uma determinada classe possua apenas uma instância, independente de quantas solicitações forem feitas.
Vamos então simular este cenário com duas classes, uma que representará nossa conexão com o banco de dados e a outra que seria uma usuária desta classe.
Abaixo o código da classe que representa nossas conexões no sistema:
public class ConexaoBanco {
/*Criamos um atributo estático que representará
* nossa única instancia desta classe no sistema
*/
private static ConexaoBanco instancia = null;
/*Aqui estamos tornando nosso construtor privado de
* forma que ele nunca possa ser utilizado por outra
* classe.
*/
private ConexaoBanco() {
}
/*Aqui nosso método que faz o serviço principal do Singleton
* ele verifica se ja existe uma instância desta classe
* caso nao exista ele cria uma e retorna o objeto
* caso exista ele simplesmente retorna o objeto que
* já existe.
*/
public static ConexaoBanco getInstancia() {
if (instancia == null) {
instancia = new ConexaoBanco();
}
return instancia;
}
}
Basicamente os passos que fizemos foram os seguintes:
- Criamos um atributo de classe referente a uma instância da classe em questão
- Tornamos nosso construtor private de forma que ele só possa ser acessado pela própria classe
- Criamos um método estático que verifica se existe uma instância da classe, caso existe ele retorna ela, caso não exista ele retorna uma nova instância.
Agora vamos a nossa classe que utiliza a classe ConexaoBanco:
public class Cliente {
public static void main(String args[]){
/*Obtemos uma instância de ConexaoBanco
* como ainda não havia nenhuma criada no sistema
* ele retorna uma nova instância.
*/
ConexaoBanco con = ConexaoBanco.getInstancia();
//Outros códigos
/*
* Obtemos outra instancia de ConexaoBanco, agora
* como ja havia uma ele retorna a instância que
* já havia sido criada no método anterior.
*/
ConexaoBanco con2 = ConexaoBanco.getInstancia();
}
}
Na nossa classe Cliente ao obtermos um objeto da classe ConexaoBanco pela primeira vez através do método ConexaoBanco.getInstancia(), este método verifica se há uma instancia da
classe criada no sistema, no nosso caso como é a primeira vez que o estamos invocando ele criará um novo objeto de ConexaoBanco e o retornará, agora quando invocarmos novamente o método
ele não criará mais instâncias da classe apenas retornará a que já foi criada anteriormente.
É isso ai, muito simples e util não?!
Abraços!
