Code Monkey home page Code Monkey logo

statemachine's Introduction

State machines

State machines in Java.

Enables both type checked and runtime checked transitions

Typechecked, if we try to transition straight from green to red it will fail to compile

interface TrafficLight extends State<TrafficLight> {}
static class Green implements TrafficLight, TransitionTo<SolidAmber> {}
static class SolidAmber implements TrafficLight, TransitionTo<Red> {}
static class Red implements TrafficLight, TransitionTo<FlashingAmber> {}
static class FlashingAmber implements TrafficLight, TransitionTo<Green> {}


@Test
public void traffic_light_typechecked_example() {
    Green signal = new Green();
    //uncomment a transition and it will fail to compile.
    signal = signal
        .transition(SolidAmber::new)
        .transition(Red::new)
        .transition(FlashingAmber::new)
        .transition(Green::new);
}

We can still have typechecked transitions even where multiple state transitions are possible

static class Pending implements OrderStatus, BiTransitionTo<CheckingOut, Cancelled> {}

pending.transition(CheckingOut::new); // fine
pending.transition(Cancelled::new);   // fine
pending.transition(Refunded::new);   // Compile Error

When using the runtime checked transitions we'd throw an exception if we can't transition

@Test
public void runtime_transitions_possible() {
   TrafficLight light = new Green();
   light = light
       .tryTransition(SolidAmber::new)
       .unchecked();

   assertTrue(light instanceof SolidAmber);
}
@Test(expected = State.InvalidStateTransitionException.class)
public void runtime_transitions_throw_exception_when_not_possible() {
    TrafficLight light = new Green();
    light = light
            .tryTransition(Red::new)
            .unchecked();
}

We can add behaviour on states so that we can perform an appropriate action for the state we're in

@Test
public void behaviour_on_states() throws OhNoes {
    Customer customer = customer("[email protected]");

    OrderStatus state = new Pending();
    state.notifyProgress(customer, emailSender);

    verifyZeroInteractions(emailSender);

    state = state
            .tryTransition(CheckingOut::new)
            .orElseThrow(OhNoes::new)
            .transition(Purchased::new);

    state.notifyProgress(customer, emailSender);

    verify(emailSender).sendEmail(customer.email(), "Your order is on its way");
    verify(emailSender).sendEmail("[email protected]", "Customer order pending");
}

interface OrderStatus extends State<OrderStatus> {
    default void notifyProgress(Customer customer, EmailSender sender) {}
}
static class Purchased implements OrderStatus, BiTransitionTo<Shipped, Failed> {
    public void notifyProgress(Customer customer, EmailSender emailSender) {
        emailSender.sendEmail("[email protected]", "Customer order pending");
        emailSender.sendEmail(customer.email(), "Your order is on its way");
    }
}
static class Cancelled implements OrderStatus {
    public void notifyProgress(Customer customer, EmailSender emailSender) {
        emailSender.sendEmail("[email protected]", "Customer order cancelled");
        emailSender.sendEmail(customer.email(), "Your order has been cancelled");
    }
}

We can also have guards before and after transitions. Our states can be non-static classes if we want to access state in the enclosing class, like this logger.

Logger failureLog = Logger.getLogger("failures");
class Failed implements OrderStatus {
    @Override
    public void afterTransition(OrderStatus from) {
        failureLog.warning("Oh bother! failed from " + from.getClass().getSimpleName());
    }
}

statemachine's People

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.