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

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.

Um Switch/Case não resolve teu problema?

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

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

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.

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.

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

Veja um exemplo com Command:

Você substitui isso:

[code]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…");
}
}
}[/code]

Por isso:

[code]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…");
}
}[/code]

[code]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();
}
}[/code]

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

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 &#123;

      private TagStrategy stategy;

      public Tag&#40;String tag&#41;&#123;
            if &#40; &quot;ler&quot;.equals&#40;tag&#41;&#41; &#123;
                stategy = LerStategy&#40;&#41;;
           &#125; else if &#40;&#41; &#123;
              // etc.. 
          &#125;
          // podemos usar a tecnica do map, mas ai ele terá que ser estático
         // e pode ter a desvantagem de criar objetos desnecessários.
      &#125;

      public void execute &#40;TagContext context&#41;&#123;
                  stategy.execute&#40;context&#41;;
      &#125;

&#125;

interface TagStrategy &#123;

  public void execute &#40;TagContext context&#41;;

&#125;
class LerStategy implements TagStrategy &#123;
  public void execute &#40;TagContext context&#41;&#123;
        // lê alguma coisa do contexto
  &#125; 

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&#40;String tag&#41;&#123;
              stategy =  TagFactory.getFactory&#40;&#41;.getStategy&#40;tag&#41;;
      &#125;


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&#40;&quot;ler&quot;&#41;;
  tag.execute&#40;context&#41;;

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