Ybadoo - Soluções em Software Livre
Tutoriais
Programação Orientada a Objetos

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.

/**
 * Copyright (C) 2009/2018 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

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 invalido");
    }
  }

  /**
   * 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);
  }
}
/**
 * Copyright (C) 2009/2018 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

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 invalido");
    }
  }

  /**
   * 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);
  }
}
/**
 * Copyright (C) 2009/2018 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

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 invalido");
    }
  }

  /**
   * 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);
  }
}
/**
 * Copyright (C) 2009/2018 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

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 invalido");
    }
  }

  /**
   * 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);
  }
}
/**
 * Copyright (C) 2009/2018 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

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 invalido");
    }
  }

  /**
   * 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.

/**
 * Copyright (C) 2009/2018 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

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.

a. apresente o diagrama de classes em UML da solução proposta.

Diagrama de Classe
Diagrama de Classe

b. quais foram os padrões de projeto do catálogo GoF que você utilizou na refatoração? Justifique a escolha dos padrões utilizados.

No processo de refatoração do sistema apresentado, utilizou-se o padrão de projeto Template Method, permitindo que as subclasses possam redefinir os métodos area e volume, conforme a representação de cada um dos sólidos platônicos. O comportamento comum dos sólidos platônicos foi concentrado numa classe comum (Poliedro) para evitar a duplicação de código, e permitir a comparação das propriedades métricas de sólidos platônicos através de polimorfismo.

c. apresente a codificação na linguagem de programação Java da classe Hexaedro após a refatoração.

/**
 * Copyright (C) 2009/2018 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

package com.ybadoo.tutoriais.poo;

/**
 * Representancao de um hexaedro 
 */
public class Hexaedro extends Poliedro
{
  /**
   * 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
  {
    super(aresta);
  }

  /* (non-Javadoc)
   * @see com.ybadoo.tutoriais.poo.Poliedro#area()
   */
  public double area()
  {
    return 6.0 * Math.pow(getAresta(), 2.0);
  }

  /* (non-Javadoc)
   * @see com.ybadoo.tutoriais.poo.Poliedro#volume()
   */
  public double volume()
  {
    return Math.pow(getAresta(), 3.0);
  }
}

d. apresente a codificação na linguagem de programação Java da classe Comparador após a refatoração.

/**
 * Copyright (C) 2009/2018 - Cristiano Lehrer (cristiano@ybadoo.com.br)
 *                  Ybadoo - Solucoes em Software Livre (www.ybadoo.com.br)
 *
 * Permission is granted to copy, distribute and/or modify this document
 * under the terms of the GNU Free Documentation License, Version 1.3
 * or any later version published by the Free Software Foundation; with
 * no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
 * A copy of the license is included in the section entitled "GNU
 * Free Documentation License".
 */

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 solido platonico
   * @param obj2 instancia do segundo solido platonico
   * @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(Poliedro obj1, Poliedro 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 solido platonico
   * @param obj2 instancia do segundo solido platonico
   * @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(Poliedro obj1, Poliedro obj2)
  {
    if(obj1.volume() > obj2.volume())
    {
      return 1;
    }

    if(obj1.volume() < obj2.volume())
    {
      return -1;
    }

    return 0;
  }
}