Os padrões de projeto (design patterns) apresentados no livro Design Patterns: Elements of Reusable Object-Oriented Software, publicado em 1995 por Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides, também conhecidos como a "Gangue dos Quatro" (Gang of Four) ou simplesmente "GoF", são organizados em três famílias, sendo:
Em um sistema de software para controlar pedidos para entrega em domicílio, deve haver uma funcionalidade que permita que o atendente solicite a repetição de um pedido anteriormente feito por um cliente. O gerente do restaurante informou que essa funcionalidade aumentaria a agilidade no atendimento aos clientes, visto que muitos deles tendem a fazer pedidos similares aos que já fizeram anteriormente. Ao usar essa funcionalidade, o atendente do restaurante seleciona um pedido cuja composição corresponde a produtos normalmente requisitados pelos clientes e solicita ao sistema a construção de um novo pedido igual ao selecionado. Esse novo pedido pode, então, ser alterado pelo atendente se o cliente solicitar a adição de novos produtos do cardápio, por exemplo. Portanto, a parte principal dessa funcionalidade corresponde a criar uma cópia de um pedido a partir de pedido preexistente. Na implementação dessa funcionalidade, seu desenvolvedor deve utilizar qual padrão de projeto do catálogo GoF (Gang of Four), dentre os listados abaixo?
Durante o desenvolvimento de um sistema para comparação das propriedades métricas de sólidos platônicos, os desenvolvedores implementaram uma classe para cada sólido platônico existente, conforme apresentado a seguir.
package com.ybadoo.tutoriais.poo;
/**
* Representancao de um tetraedro
*/
public class Tetraedro
{
/**
* Valor da aresta do tetraedro
*/
private double aresta;
/**
* Construtor para inicializar o valor da aresta do tetraedro
*
* @param aresta valor da aresta do tetraedro
* @throws IllegalArgumentException valor da aresta do tetraedro invalido
*/
public Tetraedro(double aresta) throws IllegalArgumentException
{
if(aresta >= 0.0)
{
this.aresta = aresta;
}
else
{
throw new IllegalArgumentException("Valor da aresta do "
+ "tetraedro é inválido");
}
}
/**
* Retornar a area do tetraedro
*
* @return area do tetraedro
*/
public double area()
{
return Math.sqrt(3.0) * Math.pow(aresta, 2.0);
}
/**
* Retornar o valor da aresta do tetraedro
*
* @return valor da aresta do tetraedro
*/
public double getAresta()
{
return aresta;
}
/**
* Retornar o volume do tetraedro
*
* @return volume do tetraedro
*/
public double volume()
{
return (Math.sqrt(2.0) / 12.0) * Math.pow(aresta, 3.0);
}
}
package com.ybadoo.tutoriais.poo;
/**
* Representancao de um hexaedro
*/
public class Hexaedro
{
/**
* Valor da aresta do hexaedro
*/
private double aresta;
/**
* Construtor para inicializar o valor da aresta do hexaedro
*
* @param aresta valor da aresta do hexaedro
* @throws IllegalArgumentException valor da aresta do hexaedro invalido
*/
public Hexaedro(double aresta) throws IllegalArgumentException
{
if(aresta >= 0.0)
{
this.aresta = aresta;
}
else
{
throw new IllegalArgumentException("Valor da aresta do "
+ "hexaedro é inválido");
}
}
/**
* Retornar a area do hexaedro
*
* @return area do hexaedro
*/
public double area()
{
return 6.0 * Math.pow(aresta, 2.0);
}
/**
* Retornar o valor da aresta do hexaedro
*
* @return valor da aresta do hexaedro
*/
public double getAresta()
{
return aresta;
}
/**
* Retornar o volume do hexaedro
*
* @return volume do hexaedro
*/
public double volume()
{
return Math.pow(aresta, 3.0);
}
}
package com.ybadoo.tutoriais.poo;
/**
* Representancao de um octaedro
*/
public class Octaedro
{
/**
* Valor da aresta do octaedro
*/
private double aresta;
/**
* Construtor para inicializar o valor da aresta do octaedro
*
* @param aresta valor da aresta do octaedro
* @throws IllegalArgumentException valor da aresta do octaedro invalido
*/
public Octaedro(double aresta) throws IllegalArgumentException
{
if(aresta >= 0.0)
{
this.aresta = aresta;
}
else
{
throw new IllegalArgumentException("Valor da aresta do "
+ "octaedro é inválido");
}
}
/**
* Retornar a area do octaedro
*
* @return area do octaedro
*/
public double area()
{
return 2.0 * Math.sqrt(3.0) * Math.pow(aresta, 2.0);
}
/**
* Retornar o valor da aresta do octaedro
*
* @return valor da aresta do octaedro
*/
public double getAresta()
{
return aresta;
}
/**
* Retornar o volume do octaedro
*
* @return volume do octaedro
*/
public double volume()
{
return (Math.sqrt(2.0) / 3.0) * Math.pow(aresta, 3.0);
}
}
package com.ybadoo.tutoriais.poo;
/**
* Representancao de um dodecaedro
*/
public class Dodecaedro
{
/**
* Valor da aresta do dodecaedro
*/
private double aresta;
/**
* Construtor para inicializar o valor da aresta do dodecaedro
*
* @param aresta valor da aresta do dodecaedro
* @throws IllegalArgumentException valor da aresta do dodecaedro invalido
*/
public Dodecaedro(double aresta) throws IllegalArgumentException
{
if(aresta >= 0.0)
{
this.aresta = aresta;
}
else
{
throw new IllegalArgumentException("Valor da aresta do "
+ "dodecaedro é inválido");
}
}
/**
* Retornar a area do dodecaedro
*
* @return area do dodecaedro
*/
public double area()
{
return 3.0 * Math.sqrt(25.0 + 10.0 * Math.sqrt(5.0)
* Math.pow(aresta, 2.0));
}
/**
* Retornar o valor da aresta do dodecaedro
*
* @return valor da aresta do dodecaedro
*/
public double getAresta()
{
return aresta;
}
/**
* Retornar o volume do dodecaedro
*
* @return volume do dodecaedro
*/
public double volume()
{
return 1.0/4.0 * (15.0 + 7.0 * Math.sqrt(5.0)) * Math.pow(aresta, 3.0);
}
}
package com.ybadoo.tutoriais.poo;
/**
* Representancao de um icosaedro
*/
public class Icosaedro
{
/**
* Valor da aresta do icosaedro
*/
private double aresta;
/**
* Construtor para inicializar o valor da aresta do icosaedro
*
* @param aresta valor da aresta do icosaedro
* @throws IllegalArgumentException valor da aresta do icosaedro invalido
*/
public Icosaedro(double aresta) throws IllegalArgumentException
{
if(aresta >= 0.0)
{
this.aresta = aresta;
}
else
{
throw new IllegalArgumentException("Valor da aresta do "
+ "icosaedro é inválido");
}
}
/**
* Retornar a area do icosaedro
*
* @return area do icosaedro
*/
public double area()
{
return 5.0 * Math.sqrt(3.0) * Math.pow(aresta, 2.0);
}
/**
* Retornar o valor da aresta do icosaedro
*
* @return valor da aresta do icosaedro
*/
public double getAresta()
{
return aresta;
}
/**
* Retornar o volume do icosaedro
*
* @return volume do icosaedro
*/
public double volume()
{
return 5.0/12.0 * (3.0 + Math.sqrt(5.0)) * Math.pow(aresta, 3.0);
}
}
Mas quando os desenvolvedores foram implementar a classe responsável pela comparação das propriedades métricas de sólidos platônicos, identificaram um problema, pois teriam que implementar uma função para cada uma das combinações possíveis, conforma apresentado na classe a seguir.
package com.ybadoo.tutoriais.poo;
/**
* Comparador das propriedades metricas de solidos platonicos
*/
public class Comparador
{
/**
* Comparar a area de dois solidos platonicos
*
* @param obj1 instancia do primeiro tetraedro
* @param obj2 instancia do segundo tetraedro
* @return
* 1 caso a area do primeiro seja maior do que a area do segundo,
* -1 caso a area do segundo seja maior do que a area do primeiro,
* 0 caso as areas dos dois sejam iguais
*/
public int area(Tetraedro obj1, Tetraedro obj2)
{
if(obj1.area() > obj2.area())
{
return 1;
}
if(obj1.area() < obj2.area())
{
return -1;
}
return 0;
}
/**
* Comparar a area de dois solidos platonicos
*
* @param obj1 instancia do tetraedro
* @param obj2 instancia do hexaedro
* @return
* 1 caso a area do tetraedro seja maior do que a area do hexaedro,
* -1 caso a area do hexaedro seja maior do que a area do tetraedro,
* 0 caso as areas dos dois sejam iguais
*/
public int area(Tetraedro obj1, Hexaedro obj2)
{
if(obj1.area() > obj2.area())
{
return 1;
}
if(obj1.area() < obj2.area())
{
return -1;
}
return 0;
}
/* .... */
/**
* Comparar o volume de dois solidos platonicos
*
* @param obj1 instancia do primeiro tetraedro
* @param obj2 instancia do segundo tetraedro
* @return
* 1 caso o volume do primeiro seja maior do que o volume do segundo,
* -1 caso o volume do segundo seja maior do que o volume do primeiro,
* 0 caso os volumes dos dois sejam iguais
*/
public int volume(Tetraedro obj1, Tetraedro obj2)
{
if(obj1.volume() > obj2.volume())
{
return 1;
}
if(obj1.volume() < obj2.volume())
{
return -1;
}
return 0;
}
/**
* Comparar o volume de dois solidos platonicos
*
* @param obj1 instancia do tetraedro
* @param obj2 instancia do hexaedro
* @return
* 1 caso o volume do tetraedro seja maior do que o volume do hexaedro,
* -1 caso o volume do hexaedro seja maior do que o volume do tetraedro,
* 0 caso os volumes dos dois sejam iguais
*/
public int volume(Tetraedro obj1, Hexaedro obj2)
{
if(obj1.volume() > obj2.volume())
{
return 1;
}
if(obj1.volume() < obj2.volume())
{
return -1;
}
return 0;
}
/* .... */
}
Refatore o sistema apresentado, empregando os padrões de projeto do catálogo GoF, de forma que a classe Comparador
possa realizar facilmente a comparação das propriedades métricas de sólidos platônicos.
Hexaedro
após a refatoração.Comparador
após a refatoração.Durante o desenvolvimento de um sistema para suporte a uma rede social, um desenvolvedor decidiu criar a facilidade de uma pessoa ter uma lista de amigos para poder enviar e-mails, postagens e/ou fotos. Essa lista pode conter um número indefinido de amigos ou de outras listas de amigos, criando uma estrutura recursiva. O padrão de projeto do catálogo GoF que descreve essa estrutura é:
Deseja-se que uma aplicação possa manipular diferentes tipos de bancos de dados de modo transparente às classes que necessitam de serviços de acesso a dados. Inicialmente será necessário fornecer suporte a bancos de dados XML e SQL, entretanto, novos tipos poderão ser futuramente adicionados. A solução proposta é a seguinte:
DB
) será responsável por instanciar um objeto correspondente ao tipo de banco de dados desejado. Isso será feito através do método estático getDB()
, que retornará um objeto de uma de suas subclasses concretas, de acordo com o parâmetro (tipo) passado.O diagrama de classe a seguir ilustra a estrutura descrita acima.
Qual padrão de projeto do catálogo GoF foi utilizado na solução proposta?