Diminuir uma quantidade grande de IFs, Existe algum padrão

9 respostas
M

Bom pessoal, alguém saberia me falar se existe algum padrão uma quantidade grande de IFs. Por exemplo tenho um método e dentro dele tenho vários IF´s e dependendo de cada um é tomada uma determinada atitude. Queria saber se tem como criar uma classe para tratamento de claúsula IF. Como ficaria essa classe.

9 Respostas

C

Um Switch/Case não resolve teu problema?

M

Teria como implementar esses if’s em uma classe para uma melhor flexibilidade.

P

teria q analisar o seu contexto…pode existir uma situação com uma grande quantidade de IFs…cada caso eh um caso…

normalmente isso eh causado por um design ruim…se ainda for possivel tente refazer a analise desse caso e tente um workaround para melhorar a “aparencia” do seu codigo…

flw

M

Um exemplo seria um arquivo XML aonde para determinada TAG poderia executar uma determinada ação onde nesse existiria vários tipos de TAG cada uma executando uma determinada ação.

J

Esse tipo de coisa deve ser evitada, talvez usar um switch, ou se isso é realmente grande e é uma parte importante da sua aplicação o uso de algum Design Pattern deve ser considerado, no caso do XML por exemplo, o padrão Command talvez ajude, pelo menos tente deixar a coisa mais bonita e mais facil de entender do que simplesmente um amontoado de if’s.

S

Vc precisa implementar o design pattern Strategy. Procure no forum e no goggle e se tiver duvidas diga.

J

Veja um exemplo com Command:

Você substitui isso:

public class Principal{
   public static void main(String[] args){
      Principal p = new Principal();
      p.lerXml();
   }

   public void lerXml(){
      String tag = //lê tag do XML
      if(tag.equals("falar")){
         System.out.println("Falando...");
      }else if(tag.equals("correr")){
         System.out.println("Correndo...");
      }else if(tag.equals("ler")){
         System.out.println("Lendo...");
      }
   }
}
Por isso:
public interface Command{
   public void execute();
}

public class FalarCommand implements Command{
   public void execute(){
      System.out.println("Falando...");
   }
}

public class CorrerCommand implements Command{
   public void execute(){
      System.out.println("Correndo...");
   }
}

public class LerCommand implements Command{
   public void execute(){
      System.out.println("Lendo...");
   }
}
public class Principal{
   private static Map<String, Command> comandos = new HashMap<String, Command>();

   public Principal{
      comandos.put("falar", new FalarCommand());
      comandos.put("correr", new CorrerCommand());
      comandos.put("ler", new LerCommand());
   }

   public static void main(String[] args){
      Principal p = new Principal();
      p.lerXml();
   }

   public void lerXml(){
      String tag = //lê tag do XML
      Command cmd = comandos.get(tag);
      cmd.execute();
   }
}

É só uma opção, não sei se a melhor para o seu caso, você tem que analisar.

S

O codigo que o jairelton escreveu é um bom principio para o padrão strategy (estratégia). Qual seria a diferença.

Quando se criam muitos comands , acab-se tendo que escolher entre eles.
No caso foi usado um hashMap e umas strings baseadas no tag para escolher. Bom, se incluirmos essa logica dentro de um objecto teremos o padrão strategy

class Tag {

      private TagStrategy stategy;

      public Tag(String tag){
            if ( "ler".equals(tag)) {
                stategy = LerStategy();
           } else if () {
              // etc.. 
          }
          // podemos usar a tecnica do map, mas ai ele terá que ser estático
         // e pode ter a desvantagem de criar objetos desnecessários.
      }

      public void execute (TagContext context){
                  stategy.execute(context);
      }

}

interface TagStrategy {

  public void execute (TagContext context);

}
class LerStategy implements TagStrategy {
  public void execute (TagContext context){
        // lê alguma coisa do contexto
  }

Cada strategy é como um comands, mas a escolha de qual usar é feita pela prorpia classe e não pelo programador.

Notar que eu adicionei TagContext como parametro. Bom, dependendo do que a tag tem que fazer, provavelmente ela tem que ter acesso a certo ambiente, como o request e o response , ou qq outra coisa. De forma que ela possa obter dados processá-los e produzir um output.
Isto pode tb ser usado no pattenr Command. Tudo depende do tipo de tarefas que os stategy tem que implementar.

Se houver muitos stategy , escrever ifs ou maps na mão pode ser impossivel. E o que acontece quando mais estratégias são adicionadas ? Então nesse caso podemos completar com um Abstract Factory assim

public Tag(String tag){
              stategy =  TagFactory.getFactory().getStategy(tag);
      }

Este Factory pode ser preenchido usando os mesmos ifs, ou a tecnica do map, ou pode ser carregado de um arquivo de configuração XML ou properites, sei lá… a partir dai as possibilidades são infinitas. PAra poder escolher qual tipo de factory será usado podemos usar várias tenicas , sendo o properties a mais comum (consulta o padrão Abstract Factory).

Estas tenicas são comuns em sistema configuráveis como o Ant ou o Log4J

Para usar a Tag é só fazer assim :

TagContext context =  ... // criar um apropriado
 
  Tag tag = new Tag("ler");
  tag.execute(context);
M

obrigado pessoal, vocês já deram uma luz para meu caminho.

Criado 5 de janeiro de 2007
Ultima resposta 8 de jan. de 2007
Respostas 9
Participantes 5