Máquinas de Estado Java seladas

alguns anos atrás, postei sobre como implementar máquinas de Estado que permitem apenas transições válidas em tempo de compilação em Java.

isso usava interfaces em vez de enums, o que tinha uma grande desvantagem—você não poderia garantir que conhece todos os Estados envolvidos. Alguém pode adicionar outro estado em outro lugar em sua base de código implementando a interface.

Java 15 traz um recurso de visualização de classes seladas. Classes seladas nos permitem resolver essa desvantagem. Agora, nossas máquinas de Estado baseadas em interface podem não apenas impedir transições inválidas, mas também ser enumeráveis como enums.

se você estiver usando jdk 15 com recursos de visualização habilitados, você pode experimentar o código. É assim que parece definir uma máquina de estado com interfaces.

selados interface TrafficLight se estende Estado<TrafficLight> permite Verde, SolidAmber, FlashingAmber, Vermelho {}static final da classe Verde implementa Semáforo, TransitionTo<SolidAmber> {}static final de classe SolidAmber implementa Semáforo, TransitionTo<Vermelho> {}static final de classe Vermelho implementa Semáforo, TransitionTo<FlashingAmber> {}static final de classe FlashingAmber implementa Semáforo, TransitionTo<Verde> {}

A nova peça é “selado” e “permitir”. Agora, torna-se uma falha de compilação para definir uma nova implementação de TrafficLight

, bem como o comportamento existente, onde é uma falha de tempo de compilação para executar uma transição que os semáforos não permitem.

N. B. Você também pode pular a versão verificada em tempo de compilação e ainda usar as definições de tipo para verificar as transições em tempo de execução.

Várias transições são possíveis a partir de um estado muito

static final de classe Pendentes implementa OrderStatus, BiTransitionTo<CheckingOut, Cancelado> {}

Graças a selado aulas de nós agora também pode fazer enum estilo de enumeração de pesquisas e na nossa interface baseado em máquinas de estado.

selados interface OrderStatus se estende Estado<OrderStatus> permite Pendentes, CheckingOut, Comprado, Enviado, Cancelado, Falhou, Reembolsado {} @Test public void enumerável() { assertArrayEquals( matriz(Pendente.classe, CheckingOut.Classe, comprado.Classe, enviado.Classe, cancelada.classe, falhou.classe, reembolsado.classe), Estado.valores (OrderStatus.classe)); assertEquals (0, novo pendente ().ordinal ()); assertEquals (3, Novo enviado ().ordinal ()); assertEquals (comprado.classe, Estado.valorof (OrderStatus.classe," comprado")); assertEquals(cancelado.classe, Estado.valorof (OrderStatus.classe, "cancelado"));}

isso é possível porque o JEP 360 fornece uma API de reflexão com a qual se pode enumerar as subclasses Permitidas de uma interface. (nota lateral o JEP diz getPermittedSubclasses () mas a implementação parece usar permittedSubclasses ())
podemos adicionar use isso para adicionar os métodos de conveniência acima à nossa interface de Estado para permitir as pesquisas values (), ordinal() e valueOf ().

se você estiver procurando por uma solução para o problema, por favor entre em contato conosco.de (stateMachineType.permittedSubclasses ()).mapa (Estado:: classFromDesc).coletar (toList ());} static <T extends State<T>> Class<T> valueOf(Class<T> stateMachineType, String name) { assertSealed(stateMachineType); return valuesList(stateMachineType) .stream() .filter(c -> Objects.equals(c.getSimpleName(), name)) .findFirst() .orElseThrow(IllegalArgumentException::new);}static <T extends State<T>, U extends T> int ordinal(Class<T> stateMachineType, Class<U> instanceType) { return valuesList(stateMachineType).indexOf(instanceType);}

há mais detalhes sobre como a verificação de transição funciona e mais exemplos de onde isso pode ser útil na postagem original. O código está no github.

Deixe uma resposta

O seu endereço de email não será publicado.