viernes, 24 de agosto de 2018

Design Patterns: Abstract Factory

Hey there,

Long time without writing. I would like to embrace this skill again, so my plan for it is to create a list of daily or weekly articles about design patterns and cool CS stuffs.

So lets get started.

So far we know that we have 23 popular design patterns, designed to solve well known problems in systems.

So my goal will be to analyze them 1 by 1, providing examples on how to use them. For this purpose, I will use Python, which is a language I am getting used to, and strongly recommend to learn and apply, as it is capable of incredible stuffs

OK now seriously. Lets get Started.


Creational Pattern

As the book defines it, Creational design patterns "abstract" the instantiation process. It means that the system will be independent of how their objects are created.

Pattern 1: Abstract Factory.

This one is a bit tricky. But I will read, analyze, create notes so I can get this depicted and simplify for you. Hold on. (12:41 am)


after half an hour of reading, I think the right approach to this is to explain the problem that it intends to solve.


So I am a big soccer fan (HALA Madrid!) and I want to have a way to represent different cups played in the world (I will be focusing on Europe for obvious reasons).

The concern of the abstract factory is to instantiate a group of related or dependent objects, based on a common criteria.

For our case we will define the Following requirement: A cup will contain a title, and a list of clubs that will compete against each other to win it.

So lets first design how the abstract factory for cups will look like:

class KitCup(object):

__metaclass__ = abc.ABCMeta

@abc.abstractmethod
def createTitle(self):
pass
@abc.abstractmethod
def createFavoriteClub(self):
pass

@abc.abstractmethod
def createCountry(self):
pass


KitCup will represent an abstract class, containing all the methods that creates concrete classes + sprecial functions just for printing purposes.

Now let see how everything looks like:


import abc

class Club(object):
__metaclass__ = abc.ABCMeta
NAME = '' #Should be define by Subclasses

def get_name(self):
return self.NAME

class RealMadrid(Club):
NAME = 'Real Madrid FC'

class Juventus(Club):
NAME = 'Juventus FC'

class Bayern(Club):
NAME = ' FC Bayern Munchen'


class KitCup(object):

__metaclass__ = abc.ABCMeta

@abc.abstractmethod
def createTitle(self):
pass
@abc.abstractmethod
def createFavoriteClub(self):
pass

@abc.abstractmethod
def createCountry(self):
pass
class SpainCup(KitCup):

def createCountry(self):
return 'Spain'

def createTitle(self):
return 'La liga'
def createFavoriteClub(self):
return RealMadrid()

class ItalyCup(KitCup):

def createCountry(self):
return 'Italy'

def createTitle(self):
return 'Calccio'
def createFavoriteClub(self):
return Juventus()
class GermanyCup(KitCup):

def createCountry(self):
return 'Germany'

def createTitle(self):
return 'BundesLiga'
def createFavoriteClub(self):
return Bayern()


def main():

leagues = [SpainCup, ItalyCup, GermanyCup]

print('********** Summary of favorites per league **********')
for league in leagues:
print('Country: {}'.format(league().createCountry()))
print('League Name: {}'.format(league().createTitle()))
print('Favorite Club: {}'.format(league().createFavoriteClub().get_name()))
print('<---------- ----------="" next="">')

if __name__ == '__main__':
main()


There is a lot of benefits:

  1. We defer the instantiation of concrete clubs to only when the iteration is achieved (see the for loop in the main class)
  2. We are grouping together as dependent concept things such as favorite club, name of the league and country where this cup belongs
  3. See how easy it is to scale, for instance concepts such as champions league, or world cup can be easily implemented (with small tweaks of course )
In conclusion, the main objective of the Abstract Factory is to group the creation of common concepts, leaving the concrete classes the tsk of instantiating them.

Hope you like it, see you soon!