diff --git a/finite-state-machine/etc/finite-state-machine.png b/finite-state-machine/etc/finite-state-machine.png
new file mode 100644
index 000000000000..59b3e3035e86
Binary files /dev/null and b/finite-state-machine/etc/finite-state-machine.png differ
diff --git a/finite-state-machine/pom.xml b/finite-state-machine/pom.xml
new file mode 100644
index 000000000000..ada7c8c4007b
--- /dev/null
+++ b/finite-state-machine/pom.xml
@@ -0,0 +1,15 @@
+
+
+
+ java-design-patterns
+ com.iluwatar
+ 1.5.0
+
+ 4.0.0
+
+ finite-state-machine
+
+
+
\ No newline at end of file
diff --git a/finite-state-machine/src/main/java/com/iluwatar/fsm/FiniteStateMachine.java b/finite-state-machine/src/main/java/com/iluwatar/fsm/FiniteStateMachine.java
new file mode 100644
index 000000000000..aa6bd4be0660
--- /dev/null
+++ b/finite-state-machine/src/main/java/com/iluwatar/fsm/FiniteStateMachine.java
@@ -0,0 +1,181 @@
+package com.iluwatar.fsm;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Represents a simple finite state machine implementation with a custom context and where events and states are defined as enumerations.
+ *
+ * Created by Stephen Lazarionok.
+ */
+public final class FiniteStateMachine {
+
+ private Enum> state;
+
+ private C context;
+
+ private Map transitions;
+
+ public Enum> getState() {
+ return state;
+ }
+
+ public void raiseEvent(Enum> event) {
+
+ System.out.println("Event '" + event + "' has been raised...");
+
+ // Tries to find the transition mapping by the start state and the event raised.
+ final TransitionMappingValue transitionMappingValue = transitions.get(new TransitionMappingKey(event, state));
+ if (transitionMappingValue != null) {
+
+ // Gets the target state
+ final Enum> targetState = transitionMappingValue.getState();
+
+ // Invokes the transition handler if exists
+ if (transitionMappingValue.getTransitionHandler() != null) {
+ transitionMappingValue.getTransitionHandler().handle(state, targetState, context);
+ }
+
+ final Enum> oldState = this.state;
+ this.state = targetState;
+ System.out.println("Transition from '" + oldState + "' to '" + state + "' triggered by '"+ event + "' event has been completed.");
+ }
+ else {
+ System.out.println("No available transitions found by event '" + event + "' from state '" + state + "'.");
+ }
+ }
+
+ private static final class TransitionMappingKey {
+
+ private Enum> event;
+
+ private Enum> state;
+
+ private TransitionMappingKey(Enum> event, Enum> state) {
+ this.event = event;
+ this.state = state;
+ }
+
+ public Enum> getEvent() {
+ return event;
+ }
+
+ public Enum> getState() {
+ return state;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ TransitionMappingKey that = (TransitionMappingKey) o;
+
+ if (event != null ? !event.equals(that.event) : that.event != null) return false;
+ if (state != null ? !state.equals(that.state) : that.state != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = event != null ? event.hashCode() : 0;
+ result = 31 * result + (state != null ? state.hashCode() : 0);
+ return result;
+ }
+ }
+
+ private static final class TransitionMappingValue {
+
+ private TransitionHandler transitionHandler;
+
+ private Enum> state;
+
+ public TransitionMappingValue(TransitionHandler transitionHandler, Enum> state) {
+ this.transitionHandler = transitionHandler;
+ this.state = state;
+ }
+
+ public TransitionHandler getTransitionHandler() {
+ return transitionHandler;
+ }
+
+ public Enum> getState() {
+ return state;
+ }
+ }
+
+ private FiniteStateMachine() {
+ }
+
+ /**
+ * A builder for custom finite state machines.
+ *
+ */
+ public static final class Builder {
+
+
+ private Enum> state;
+
+ private C context;
+
+ private Map transitions = new HashMap();
+
+ private Builder() {
+ }
+
+ /**
+ * Creates a new builder.
+ * @return a new builder instance.
+ */
+ public static Builder create() {
+ return new Builder();
+ }
+
+ /**
+ * Defines an initial state.
+ * @param state
+ * @return
+ */
+ public Builder withDefaultState(final Enum> state) {
+ this.state = state;
+ return this;
+ }
+
+ /**
+ * Add a transition.
+ * @param from - 'from' state
+ * @param event - an event that triggers the transition
+ * @param to - 'to' state
+ * @param transitionHandler - a transition handler.
+ * @return
+ */
+ public Builder addTransition(final Enum> from, final Enum> event, final Enum> to, final TransitionHandler transitionHandler) {
+ transitions.put(new TransitionMappingKey(event, from), new TransitionMappingValue(transitionHandler, to));
+ return this;
+ }
+
+ /**
+ * Defines the context of the FSM. Might be used to pass external services to handle transitions within the FSM.
+ * @param context
+ * @return
+ */
+ public Builder withContext(final C context) {
+ this.context = context;
+ return this;
+ }
+
+ /**
+ * Builds a FSM based on the rules defined.
+ * @return
+ */
+ public FiniteStateMachine build() {
+ final FiniteStateMachine result = new FiniteStateMachine();
+ result.context = context;
+ result.transitions = transitions;
+ result.state = state;
+ return result;
+ }
+ }
+
+}
diff --git a/finite-state-machine/src/main/java/com/iluwatar/fsm/TransitionHandler.java b/finite-state-machine/src/main/java/com/iluwatar/fsm/TransitionHandler.java
new file mode 100644
index 000000000000..9689d3168aaf
--- /dev/null
+++ b/finite-state-machine/src/main/java/com/iluwatar/fsm/TransitionHandler.java
@@ -0,0 +1,18 @@
+package com.iluwatar.fsm;
+
+/**
+ * Represents a hook that handles transitions from one to another state.
+ *
+ * Created by Stephen Lazarionok.
+ */
+public interface TransitionHandler {
+
+ /**
+ * Handles a transition from one to another state.
+ *
+ * @param from - an initial state
+ * @param to - a target state
+ * @param context - a custom context passed.
+ */
+ void handle(Enum> from, Enum> to, C context);
+}
diff --git a/finite-state-machine/src/main/java/com/iluwatar/fsm/sample/Car.java b/finite-state-machine/src/main/java/com/iluwatar/fsm/sample/Car.java
new file mode 100644
index 000000000000..3effd6911a1c
--- /dev/null
+++ b/finite-state-machine/src/main/java/com/iluwatar/fsm/sample/Car.java
@@ -0,0 +1,15 @@
+package com.iluwatar.fsm.sample;
+
+/**
+ * Created by Stephen Lazarionok.
+ */
+public class Car {
+
+ public void drive() {
+ System.out.println("***************************");
+ System.out.println("***************************");
+ System.out.println("Driving...");
+ System.out.println("***************************");
+ System.out.println("***************************");
+ }
+}
diff --git a/finite-state-machine/src/main/java/com/iluwatar/fsm/sample/Sample.java b/finite-state-machine/src/main/java/com/iluwatar/fsm/sample/Sample.java
new file mode 100644
index 000000000000..0a1b6bc2abc4
--- /dev/null
+++ b/finite-state-machine/src/main/java/com/iluwatar/fsm/sample/Sample.java
@@ -0,0 +1,56 @@
+package com.iluwatar.fsm.sample;
+
+import com.iluwatar.fsm.FiniteStateMachine;
+import com.iluwatar.fsm.TransitionHandler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * A demo application that shows how to work with traffic lights.
+ *
+ * Created by Stephen Lazarionok.
+ */
+public class Sample {
+
+ public static void main(final String[] args) {
+
+ // Build a simple context based on map
+ final Map context = new HashMap();
+ context.put("mycar", new Car());
+
+ // A handler that just logs a transition
+ final TransitionHandler