Simple-Builder-Pattern

04 Jul 2020

Builder Pattern: Building human objects

Let us assume a scenario where in we want to develop a system to store details of all Humans on the earth. Let us start quickly from simpler things without wasting much time in what we are going to do. Here I will be gradually creating a system similar to the marvel universe. Starting from very first entity known to all of us the human-beings on Earth. I have decided to go with python for this. I will start with very basic requirement of our trageted system and will implement it using suitable design pattern. While trying to keep the overall design clean and SOLID we may need to restructure many things as and when required. This is my attempt to explore most of the python paradigm starting from OOPs then moving towards many fascinating concepts.

Let us start from attributes of human being:

When we say human being we visualize some attributes. Like gender, address, physic, financial status, occupation, IQ, hobbies, education, contact number, ID, body mark, signature and so on.

Below is the basic Human Class which could be found in the human.py

class Human:
    def __init__(
        self,
        gender=None,
        physic=None,
        financial_status=None,
        occupation=None,
        iq=None,
        hobbies=None,
        education=None,
        contact_number=None,
        identity=None,
        body_mark=None,
        signature_scans=None,
        date_of_birth=None,
        name=None,
    ):
        self.gender = gender
        self.physic = physic
        self.financial_status = financial_status
        self.occupation = occupation
        self.iq = iq
        self.hobbies = hobbies
        self.education = education
        self.contact_number = contact_number
        self.body_mark = body_mark
        self.identity = identity
        self.signature_scans = signature_scans
        self.date_of_birth = date_of_birth
        self.name = name

    def __str__(self):
        return (
            "gender ="
            + self.gender
            + "physic="
            + self.physic
            + "financial status="
            + self.financial_status
            + "occupation ="
            + self.occupation
            + "iq="
            + self.iq
            + "hobbies ="
            + self.hobbies
            + "education="
            + self.education
            + " concat_number= "
            + self.contact_number
            + "identity= "
            + self.identity
            + "body_mark="
            + self.body_mark
            + "signature_scans="
            + self.signature_scans
            + "date_of_birth="
            + self.date_of_birth
            + "name="
            + self.name
        )

The above structure is a class which is a file with name human.py. After initalizing the object of this class, memory is allocated from the RAM. Whenever system wants to access this block of memory it needs its definition. For which it refers to its type which in our case is class.Let us initialize the human class.

    tony_stark = Human(gender ='Male',
    physic='5.4ft 100 lbs brown hair blue eyes', 
    financial status='very rich',
    occupation ='scientist weapon business', 
    iq = '300', 
    hobbies ='reading discovering', 
    education= 'phd', 
    concat_number= '', 
    Id= 'ASO4389504', 
    body_mark='heat_light', 
    signature_scans='eye', 
    date_of_birth="may 29th, 1970")

In order to print the details of our object using print statement we have overwrite a str().This is also known as string representation of object. So now our class is like this. Now on printing the object we get this: As I said earlier a memory location wherein all these values are saved is the object. So let us see how

id(tony_stark)
139989539594592

and whatever is stored in memory to access it our run-time environment must know what structure it is of. So our runtime libs which manages these storage must know the kind of object in order to read it appropriately. To know the type of the object

type(tony_stark)
<class 'oop.human.Human'>

Now let us dig into some other details of design. As you could see assigning all values to this human class while initializing is hectic. We need to gather so many values during initialization. Let us consider an example, where we are getting individual value of 1000 humans in a loop that too 1 value at a time, then how we will initialize the object. As seen above all variables are public and we don’t need getter setter thus we can access any property anywhere as shown here

tony_stark = Human()
tony_stark.gender = gender

The flaw here is we need our property value public. What if our values are not public. Then we will either need setter getter or below is another approach.One thing we can do is save all values and then initialize the object. To avoid these situation a better solution is the builder design. This we use when there are too many properties and we are getting values few at one time and rest at other. So the builder pattern for this is given in human_builder.py:

class HumanBuilder(Object):
    def __init__():
        pass

    def name(self, name):
        self.__name = name
        return self

    def gender(self, gender):
        self.__gender = gender
        return self

    def physic(self, physic):
        self.__physic = physic
        return self

    def financial_status(self, financial_status):
        self.__financial_status = financial_status
        return self

    def occupation(self, occupation):
        self.__occupation = occupation
        return self

    def iq(self, iq):
        self.__iq = iq
        return self

    def hobbies(self, hobbies):
        self.__hobbies = hobbies
        return self

    def education(self, education):
        self.__education = education
        return self

    def contact_number(self, contact_number):
        self.__contact_number = contact_number
        return self

    def identity(self, identity):
        self.__identity = identity
        return self

    def body_mark(self, body_mark):
        self.__body_mark = body_mark
        return self

    def signature_scans(self, signature_scans):
        self.__signature_scans = signature_scans
        return self

    def date_of_birth(self, date_of_birth):
        self.__date_of_birth = date_of_birth
        return self

    def build()
        human = human(gender = self.__gender,
        name= self.__name, physic = self.__physic,
        financial_status = self.financial_status,
        occupation = self.__occupation, iq = self.iq,
        hobbies = self.__hobbies,
        education= self.__education,
        contact_number = self.__contact_number,
        Id = self.__id,
        body_mark = self.__body_mark,
        signature_scans = self.__signature_scans,
        date_of_birth = self.__date_of_birth)
        return human

As you may have noticed that the HumanBuilder is not as per the PEP8‘s suggestions but our Human object is. So the purpose of builder is accomplished without disturbing the PEP8 with respect to our object Human. Let us go ahead and create some humans.

    tony_stark_builder = HumanBuilder()
    tony_stark_builder.name('Tony Stark')
                .gender('Male')
                .
                .
                .
    howard_stark = howard_stark_builder()
    howard_stark.name('Howard Stark')
                .gender('Male')
                .occupation('')
    maria_stark = Maria_Stark_Builder()
    maria_stark_builder.name('Maria Stark')
                       .gender('Female')

As you may have notice there is one major thing lacking here and that is the relations between the humans. Accepting the facts provided by the Science Humans are born from Humans. So how shall we present the relationships. How to answer this question. As we all know the word relation means association with some one. So it obviously requires atleast two same subjects. In our case it is humans. In every relation both associates has some role to play. So we must know the role of the human in that relation. Let us assume all roles in binary relation are left to right. For example to represent relation below could be the code found in relation.py:

class Relation(Object):
    def __init__(left_entity=None, right_entity=None):
        self.left_entity = left_entity
        self.right_entity = right_entity

    def relation():
        return {"left_entity": self.left_entity, "right_entity": self.right_entity}

For Husband Wife relation. It is here

class HusbandWife(Relation):
    def __init__(husband=None, wife=None):
        if isinstance(husband, "Human") and isinstance(wife, "Human"):
            super().__init__(left_entity=husband, right_entity=wife)
        else:
            print("husband and wife must belong to same entity type")

    def husband():
        return self.left_entity

    def wife():
        return self.wife

    def relation():
        return {"husband": self.left_entity, "wife": self.right_entity}

So using our relationship we can use it for our above human example as follows:

stark_husband_wife = HusbandWife(howard_stark, maria_stark)
type(stark_husband_wife)
<class 'oop.relation.husband_wife.HusbandWife'>

Comments

Join the discussion for this article on this ticket. Comments appear on this page instantly.