3
respostas

Padrão State com Factory Method

Estou colocando em prática o conhecimento das aulas e gostaria de saber como criar uma fábrica de estados sem utilizar aquele monte de if comparando com o Enum do estado.

Por exemplo: Eu tenho um atendimento que pode ter vários estados. Eu gostaria de criar o AtendimentoState sem usar esse monte de if:

public class FactoryAtendimentoState {    

    @Autowired
    protected ApplicationContext applicationContext;

    public AtendimentoState getAtendimentoState(StatusAtendimentoEnum status) {

        // Verifica o status do atendamento para criação da instancia certa para o status
        if (StatusAtendimentoEnum.AGENDADO == status) {
            return applicationContext.getBean(AtendimentoAgendado.class);
        }
        else  if(StatusAtendimentoEnum.ENCAMINHADO == status) {
            return applicationContext.getBean(AtendimentoEncaminhado.class);
        }    
        else  if(StatusAtendimentoEnum.ENCERRADO == status) {
            return applicationContext.getBean(AtendimentoEncerrado.class);
        }        
        else 
            return applicationContext.getBean(AtendimentoDesistente.class);

    }

Eu tentei fazer dessa forma, mas fiquei na dúvida como seria a interação com o frontend.. (estou usando Rest)


public class FactoryAtendimentoState {    

    @Autowired
    protected ApplicationContext applicationContext;    

    public static AtendimentoState getAtendimentoState2(AtendimentoState atendimentoState) {
        return atendimentoState.getIntanciaNova();    
    }
    }

Aí cada estado ficaria parecido com isso:


public class AtendimentoAgendado extends AtendimentoState {
@Override
    public AtendimentoState getIntanciaNova() {
        return applicationContext.getBean(AtendimentoAgendado.class);
    }
//....
}

Alguém pode me ajudar? É Possível fazer o que desejo?

3 respostas

Oi Elisangela,

Pode ser desse jeito que voce fez, pois cada classe tera que sobrescrever o metodo getIntanciaNova(), eliminando com isso os ifs.

Ou cada constante do proprio enum poderia devolver sua classe associada:

public class FactoryAtendimentoState {

    @Autowired
    protected ApplicationContext applicationContext;

    public AtendimentoState getAtendimentoState(StatusAtendimentoEnum status) {
        return applicationContext.getBean(status.getClasse());
    }

}
public enum StatusAtendimentoEnum {

    AGENDADO(new AtendimentoAgendado()),
    ENCAMINHADO(new AtendimentoEncaminhado()),
    ENCERRADO(new AtendimentoEncerrado()),
    DESISTENTE(new AtendimentoDesistente());

    private final AtendimentoState classe;

    private StatusAtendimentoEnum(AtendimentoState classe) {
        this.classe = classe;
    }

    public AtendimentoState getClasse() {
        return this.classe;
    }

}

Obrigada Rodrigo Ferreira!

Vou deixar registrado como fiz. Não sei se é a melhor solução, mas está funcionando por hora.

public enum AtendimentoStateFactoryEnum {

    AGENDADO( new AtendimentoAgendado()), 
    ENCAMINHADO(new AtendimentoEncaminhado()), 
    ENCERRADO(new AtendimentoEncerrado()),
    DESISTENTE(new AtendimentoDesistente());

    private AtendimentoState classe;

    private AtendimentoStateFactoryEnum(AtendimentoState classe) {
        this.classe = classe;
    }

    public AtendimentoState getClasse() {
        return this.classe;
    }

    public static AtendimentoState toStateName(String name) {

        if (name == null || name.isEmpty()) {
            throw new ThanosException("Enum inválido:  " + name);
        }

        for (AtendimentoStateFactoryEnum x : AtendimentoStateFactoryEnum.values()) {
            if (name.equals(x.name())) {
                return x.getClasse();
            }
        }

        throw new ThanosException("Enum inválido:  " + name);
    }

}
public AtendimentoState getAtendimentoState(Atendimento atendimento) {        

    //TODO: testar mais
     public AtendimentoState getAtendimentoState(StatusAtendimentoEnum status) {
            return AtendimentoStateFactoryEnum.toStateName(status.name());
     }
}

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software