2
respostas

Design Pattern State no spring

minha duvida é a seguinte, tenho uma aplicação de pedidos e ele tem os status do pedido, tentei aplicar o padrão State para nao ter if else para nao permitir voltar o estado da aplicação, acho que implementei certo mas esta faltando um detalhe ele funciona mas porem no final ainda dependo do if e else

@Entity
public class Pedido {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private LocalDateTime dataPedido;

    @Enumerated(EnumType.STRING)
    private Status status;


    // @Enumerated(EnumType.STRING)
    @NotNull
    private FormaPagamento formaPagamento;
    //  @Enumerated(EnumType.STRING)
    @NotNull
    private FormaEntrega formaEntrega;

    @Embedded
    private SituacaoPedido situacaoPedido;

    @ManyToOne
    private Entregador entregador;

    @ManyToOne
    private Cliente cliente;


    @ManyToOne
    private Empresa empresa;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "pedido")
    private List<Produto> produtos = new ArrayList<>();


    public void cadastro() {
        this.situacaoPedido.cadastrado(this);
    }

    public void concluido() {
        situacaoPedido.concluido(this);
    }

    public void emAtendimento() {
        situacaoPedido.emAtendimento(this);
    }

    public void entregaConfirmada() {
        situacaoPedido.entregaConfirmada(this);
    }

    public void entregue() {
        situacaoPedido.entregue(this);
    }


}




@Embeddable
@Component
public abstract class SituacaoPedido {


    public void cadastrado(Pedido pedido) {
        throw new StatusPedidoException();
    }

    public void emAtendimento(Pedido pedido) {
        throw new StatusPedidoException();
    }

    public void concluido(Pedido pedido) {
        throw new StatusPedidoException();
    }

    public void entregaConfirmada(Pedido pedido) {
        throw new StatusPedidoException();
    }

    public void entregue(Pedido pedido) {
        throw new StatusPedidoException();

    }
}




public class Cadastrado extends SituacaoPedido{


    @Override
    public void emAtendimento(Pedido pedido) {

       
                pedido.setSituacaoPedido(new EmAtendimento());
                pedido.setStatus(Status.EM_ATENDIMENTO);
          
    }

}


public class Concluido extends SituacaoPedido {


    @Override
    public void entregaConfirmada(Pedido pedido) {
            pedido.setSituacaoPedido(new EntregaConfirmada());
            pedido.setStatus(Status.ENTREGA_CONFIRMADA);
    }

}






public class EmAnalise extends  SituacaoPedido {


    @Override
    public void cadastrado(Pedido pedido){
        pedido.setSituacaoPedido(new Cadastrado());
        pedido.setStatus(Status.CADASTRADO);
    }
}



public class EmAtendimento extends SituacaoPedido {


    @Override
    public void concluido(Pedido pedido) {
            pedido.setSituacaoPedido(new Concluido());
            pedido.setStatus(Status.CONCLUIDO);
    }

}



public class EntregaConfirmada extends SituacaoPedido {


    public void entregue(Pedido pedido) {

            pedido.setSituacaoPedido(new Entregue());
            pedido.setStatus(Status.ENTREGUE);
    }
}

metodo da service : se eu nao tiver esse if nao consigo fazer com que ele nao volte para um estado anterior

public PedidoDto atualizarPedidoParaEmAtendimento(Long id) {

      Pedido pedido = verificaPedido(id);

      if (pedido.getSituacaoPedido() instanceof EmAnalise) {
          pedido.setSituacaoPedido(new Cadastrado());
          pedido.emAtendimento();
          return getPedidoDto(pedido);

      }

      throw new StatusPedidoException();
  }
  
  
  
   private PedidoDto getPedidoDto(Pedido pedido) {
      pedido.setDataPedido(pedido.getDataPedido());
      pedido.setEntregador(pedido.getEntregador());
      pedido.setEmpresa(pedido.getEmpresa());
      pedido.setFormaEntrega(pedido.getFormaEntrega());
      pedido.setFormaPagamento(pedido.getFormaPagamento());

      pedidoRepository.save(pedido);

      return modelMapper.map(pedido, PedidoDto.class);
  }
2 respostas

Olá, Rodrigo!

Uma alternativa para evitar o uso de if e else nesse método é utilizar o padrão State de forma mais completa. Ao invés de verificar o tipo da situação atual do pedido e tomar a decisão com base nisso, você pode delegar essa responsabilidade para a própria situação atual do pedido.

Por exemplo, ao invés de fazer:

if (pedido.getSituacaoPedido() instanceof EmAnalise) {
    // atualizar para EmAtendimento
    // ...
}

Você pode fazer:

pedido.getSituacaoPedido().emAtendimento(pedido);

Dessa forma, a própria situação atual do pedido será responsável por atualizar o pedido para o próximo estado. Assim, você evita o uso de if e else no método atualizarPedidoParaEmAtendimento.

Porém, é importante ressaltar que, mesmo utilizando o padrão State, pode ser necessário fazer algumas verificações para garantir que a transição de estados seja válida. Por exemplo, você pode verificar se o pedido está na situação correta antes de chamar o método emAtendimento.

Espero que essa sugestão possa te ajudar a evitar o uso de if e else nesse método. Se tiver mais alguma dúvida, é só me perguntar!

Espero ter ajudado e bons estudos!

ja tentei dessa forma mas tomo null exception, ele fala que vem nem nulo o pedido.getSituacao, nao entendo porque o pedido nao salva a isso junto com o resto.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

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