master
diff --git a/3-tier.py b/3-tier.py
index a1cd30c1..625870a3 100644
--- a/3-tier.py
+++ b/3-tier.py
@@ -12,12 +12,11 @@ class Data(object):
     }
 
     def __get__(self, obj, klas):
-        print ("(Fetching from Data Store)")
+        print("(Fetching from Data Store)")
         return {'products': self.products}
 
 
 class BusinessLogic(object):
-
     """ Business logic holding data store instances """
 
     data = Data()
diff --git a/README.md b/README.md
index 98550102..492a3378 100644
--- a/README.md
+++ b/README.md
@@ -25,6 +25,7 @@ Current Patterns:
 | [decorator](decorator.py) | wrap functionality with other functionality in order to affect outputs |
 | [facade](facade.py) | use one class as an API to a number of others |
 | [factory_method](factory_method.py) | delegate a specialized function/method to create instances |
+| [front_controller](front_controller.py) | single handler requests coming to the application |
 | [flyweight](flyweight.py) | transparently reuse existing instances of objects with similar/identical state |
 | [graph_search](graph_search.py) | (graphing algorithms, not design patterns) |
 | [lazy_evaluation](lazy_evaluation.py) | lazily-evaluated property pattern in Python |
@@ -36,6 +37,7 @@ Current Patterns:
 | [prototype](prototype.py) | use a factory and clones of a prototype for new instances (if instantiation is expensive) |
 | [proxy](proxy.py) | an object funnels operations to something else |
 | [publish_subscribe](publish_subscribe.py) | a source syndicates events/data to 0+ registered listeners |
+| [specification](specification.py) |  business rules can be recombined by chaining the business rules together using boolean logic |
 | [state](state.py) | logic is org'd into a discrete number of potential states and the next state that can be transitioned to |
 | [strategy](strategy.py) | selectable operations over the same data |
 | [template](template.py) | an object imposes a structure but takes pluggable components |
diff --git a/adapter.py b/adapter.py
index 65f03cbb..374d01fb 100644
--- a/adapter.py
+++ b/adapter.py
@@ -37,7 +37,6 @@ def make_noise(self, octane_level):
 
 
 class Adapter(object):
-
     """
     Adapts an object by replacing methods.
     Usage:
diff --git a/front_controller.py b/front_controller.py
new file mode 100644
index 00000000..e6a4939d
--- /dev/null
+++ b/front_controller.py
@@ -0,0 +1,75 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+@author: Gordeev Andrey <gordeev.and.and@gmail.com>
+The controller provides a centralized entry point that controls and manages
+request handling.
+"""
+
+
+class MobileView(object):
+    def show_index_page(self):
+        print('Displaying mobile index page')
+
+
+class TabletView(object):
+    def show_index_page(self):
+        print('Displaying tablet index page')
+
+
+class Dispatcher(object):
+    def __init__(self):
+        self.mobile_view = MobileView()
+        self.tablet_view = TabletView()
+
+    def dispatch(self, request):
+        if request.type == Request.mobile_type:
+            self.mobile_view.show_index_page()
+        elif request.type == Request.tablet_type:
+            self.tablet_view.show_index_page()
+        else:
+            print('cant dispatch the request')
+
+
+class RequestController(object):
+    """ front controller """
+    def __init__(self):
+        self.dispatcher = Dispatcher()
+
+    def dispatch_request(self, request):
+        if isinstance(request, Request):
+            self.dispatcher.dispatch(request)
+        else:
+            print('request must be a Request object')
+
+
+class Request(object):
+    """ request """
+
+    mobile_type = 'mobile'
+    tablet_type = 'tablet'
+
+    def __init__(self, request):
+        self.type = None
+        request = request.lower()
+        if request == self.mobile_type:
+            self.type = self.mobile_type
+        elif request == self.tablet_type:
+            self.type = self.tablet_type
+
+
+if __name__ == '__main__':
+    front_controller = RequestController()
+    front_controller.dispatch_request(Request('mobile'))
+    front_controller.dispatch_request(Request('tablet'))
+
+    front_controller.dispatch_request(Request('desktop'))
+    front_controller.dispatch_request('mobile')
+
+
+### OUTPUT ###
+# Displaying mobile index page
+# Displaying tablet index page
+# cant dispatch the request
+# request must be a Request object
\ No newline at end of file
diff --git a/specification.py b/specification.py
new file mode 100644
index 00000000..5c885e98
--- /dev/null
+++ b/specification.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""
+@author: Gordeev Andrey <gordeev.and.and@gmail.com>
+
+Specification provide recombination business logic by
+chaining together using boolean logic
+"""
+
+from abc import abstractmethod
+
+
+class Specification(object):
+
+    def and_specification(self, candidate):
+        raise NotImplementedError()
+
+    def or_specification(self, candidate):
+        raise NotImplementedError()
+
+    def not_specification(self):
+        raise NotImplementedError()
+
+    @abstractmethod
+    def is_satisfied_by(self, candidate):
+        pass
+
+
+class CompositeSpecification(Specification):
+    @abstractmethod
+    def is_satisfied_by(self, candidate):
+        pass
+
+    def and_specification(self, candidate):
+        return AndSpecification(self, candidate)
+
+    def or_specification(self, candidate):
+        return OrSpecification(self, candidate)
+
+    def not_specification(self):
+        return NotSpecification(self)
+
+
+class AndSpecification(CompositeSpecification):
+    _one = Specification()
+    _other = Specification()
+
+    def __init__(self, one, other):
+        self._one = one
+        self._other = other
+
+    def is_satisfied_by(self, candidate):
+        return bool(self._one.is_satisfied_by(candidate) and
+                    self._other.is_satisfied_by(candidate))
+
+
+class OrSpecification(CompositeSpecification):
+    _one = Specification()
+    _other = Specification()
+
+    def __init__(self, one, other):
+        self._one = one
+        self._other = other
+
+    def is_satisfied_by(self, candidate):
+        return bool(self._one.is_satisfied_by(candidate) or
+                    self._other.is_satisfied_by(candidate))
+
+
+class NotSpecification(CompositeSpecification):
+    _wrapped = Specification()
+
+    def __init__(self, wrapped):
+        self._wrapped = wrapped
+
+    def is_satisfied_by(self, candidate):
+        return bool(not self._wrapped.is_satisfied_by(candidate))
+
+
+class User(object):
+
+    def __init__(self, super_user=False):
+        self.super_user = super_user
+
+
+class UserSpecification(CompositeSpecification):
+
+    def is_satisfied_by(self, candidate):
+        return isinstance(candidate, User)
+
+
+class SuperUserSpecification(CompositeSpecification):
+
+    def is_satisfied_by(self, candidate):
+        return getattr(candidate, 'super_user', False)
+
+
+if __name__ == '__main__':
+    print('Specification')
+    andrey = User()
+    ivan = User(super_user=True)
+    vasiliy = 'not User instance'
+
+    root_specification = UserSpecification().\
+        and_specification(SuperUserSpecification())
+
+    print(root_specification.is_satisfied_by(andrey))
+    print(root_specification.is_satisfied_by(ivan))
+    print(root_specification.is_satisfied_by(vasiliy))
+
+
+### OUTPUT ###
+# Specification
+# False
+# True
+# False

Added two patterns: front controller and specification.
pep8 minor code edit.
