Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are middlewares an implementation of the Decorator pattern?

In Django, there is the idea of Middleware. It consists of changing the requests and passing it down to the next middleware and so on, and doing the reverse with the responses.

Are middlewares implementation of the design pattern Decorator? Are they a particular case of the decorator? What are the differences between them?

Also, what is the difference between the implementation of Decorator in Django and the GoF description of it?

like image 638
thyago stall Avatar asked Feb 08 '18 23:02

thyago stall


2 Answers

Middleware and decorators are similar and can do the same job. They provide a means of inserting intermediary effects either before or after other effects downstream in the chain/stack.

A difference is that the middleware pipeline is computed using a reduction that presents the middleware with a simpler interface that hides the next middleware object in the chain. Rather it presents a next function that applies the message to that object using the correct interface (e.g. IHandler.handle).

Another difference is that it is easier to dynamically add/remove middleware because it exists in the middle of a container object (e.g. in an array) and the pipeline can be assembled on demand. A decorator is a stack of Russian dolls and its stack cannot so easily be rejiggered.

like image 168
Mario Avatar answered Nov 10 '22 06:11

Mario


Middlewares are not themselves decorators but it is possible to make decorators out of middlewares using a couple of built in functions in Django:

def decorator_from_middleware(middleware_class):
"""
Given a middleware class (not an instance), return a view decorator. This
lets you use middleware functionality on a per-view basis. The middleware
is created with no params passed.
"""
    return make_middleware_decorator(middleware_class)()

def decorator_from_middleware_with_args(middleware_class):
"""
Like decorator_from_middleware, but return a function
that accepts the arguments to be passed to the middleware_class.
Use like::

     cache_page = decorator_from_middleware_with_args(CacheMiddleware)
     # ...

     @cache_page(3600)
     def my_view(request):
         # ...
"""
    return make_middleware_decorator(middleware_class)
like image 38
Kevin L. Avatar answered Nov 10 '22 05:11

Kevin L.