Saturday, September 2, 2023

Iterator Design Pattern in Python...

Iterator design pattern is a behavioral design pattern that lets you access the element of a complex data structure - a collection class - without the knowledge of the internal structure of the elements it is accessing.

To create an iterator in Python, there are two abstract classes from the built-in `collections` module - Iterable, and Iterator. We need to implement the

`__iter__()` method in the iterated object (collection), and the `__next__ ()` method in the iterator.

The concrete class that implements the Iterator class provides various means of different ways of iteration through the collection class.

In our example, AlphabeticalOrderIterator is such a class that has provided forward and reverse ways of iteration. In this example, the WordsCollection class represents a collection of words and implements the Iterable interface.

The source code is as follows:

from collections.abc import Iterator, Iterable
from typing import Any, List

class WordsCollection(Iterable):
def __init__(self, collection: List[Any]=[]):
self._collection = collection

def __iter__(self):
return AlphabeticalOrderIterator(self._collection)

def get_reverse_iterator(self):
return AlphabeticalOrderIterator(self._collection, True)

def add_item(self, item:Any):
self._collection.append(item)

class AlphabeticalOrderIterator(Iterator):
_position = None
_reverse = False

def __init__(self, collection : WordsCollection, reverse: bool = False):
self._collection = collection
self._reverse = reverse
self._position = -1 if self._reverse else 0

def __next__(self):
try:
value = self._collection[self._position]
self._position += -1 if self._reverse else 1
except IndexError:
raise StopIteration()

return value


# Press the green button in the gutter to run the script.
if __name__ == '__main__':
wordsCollection = WordsCollection()
wordsCollection.add_item("Som")
wordsCollection.add_item("Reema")
wordsCollection.add_item("Ridit")

print("Forward traversal:")
print("\n".join(wordsCollection))
print("")

print("Reverse traversal:")
print("\n".join(wordsCollection.get_reverse_iterator()), end="")

If we run the above program the output will be as follows:

Forward traversal:

Som

Reema

Ridit


Reverse traversal:

Ridit

Reema

Som

 

Friday, September 1, 2023

Prototype Design Pattern in Python...

The prototype design pattern is a creational pattern.

If the creation of an object is a very costly affair and we already have a similar kind of object, instead of creating it each time we need it, we use the clone of the object that is already there.

Suppose, there is a large object with many attributes whose data we read from a database. We need to modify that data multiple times in our program. So instead of creating the object each time by reading from the database, we tend to keep a prototype object - we clone it, and then work on it.

In Python, there is a module called copy which has two methods - copy() and deepcopy(). The first one is for the shallow copy and the second one is for the deepcopy.

Here is the source code of an example of the Prototype design pattern.

from abc import ABC, abstractmethod
import copy

class Person(ABC):
def __init__(self, name):
self._name = name
def set_name(self, name):
self._name = name
def get_name(self):
return self._name
@abstractmethod
def clone(self):
pass
@abstractmethod
def display(self):
pass

class Teacher(Person):
def __init__(self, name, course):
super().__init__(name)
self._course = course
def set_course(self, course):
self._course = course
def get_course(self):
return self._course
def display(self):
print("\nTeacher's name : ", self._name, "\n")
print("\nHe teaches : ", self.get_course())

def clone(self):
return copy.deepcopy(self)

class Student(Person):
def __init__(self, name, teacher):
super().__init__(name)
self._teacher = teacher

def display(self):
print("\n Student's name : ", self.get_name())
print("\n Taught by : ", self._teacher.get_name())
print("\n Enrolled in the subject : ", self._teacher.get_course())

def clone(self):
return copy.deepcopy(self)



if __name__ == '__main__':
teacher = Teacher('Som', "Python Design Patttern")
teacherClone1 = teacher.clone()

student = Student ("Ridit", teacherClone1)

studentClone1 = student.clone()

teacherClone1.set_course("DSA")

teacherClone1.display()

studentClone1.display()



If we run the above piece of code the result will be as follows:

Teacher's name :  Som 

He teaches :  Python Design Patttern

Teacher's name :  Som 

He teaches :  DSA

Student's name :  Ridit

Taught by :  Som

Enrolled in the subject :   Python Design Patttern


As you can see, we have used deep copy here.