diff --git a/design-patterns/Command-Python/command.png b/design-patterns/Command-Python/command.png new file mode 100644 index 0000000..c4b0f71 Binary files /dev/null and b/design-patterns/Command-Python/command.png differ diff --git a/design-patterns/Command-Python/command.py b/design-patterns/Command-Python/command.py new file mode 100644 index 0000000..1fd8d1d --- /dev/null +++ b/design-patterns/Command-Python/command.py @@ -0,0 +1,89 @@ +class Screen(object): + def __init__(self, text=''): + self.text = text + self.clip_board = '' + + def cut(self, start=0, end=0): + self.clip_board = self.text[start:end] + self.text = self.text[:start] + self.text[end:] + + def paste(self, offset=0): + self.text = self.text[:offset] + self.clip_board + self.text[offset:] + + def clear_clipboard(self): + self.clip_board = '' + + def length(self): + return len(self.text) + + def __str__(self): + return self.text + +# Screen command interface +class ScreenCommand(object): + def __init__(self, screen): + self.screen = screen + self.previous_state = screen.text + + def execute(self): + pass + + def undo(self): + pass + +# Concrete commands +class CutCommand(ScreenCommand): + def __init__(self, screen, start=0, end=0): + super().__init__(screen) + self.start = start + self.end = end + + def execute(self): + self.screen.cut(start=self.start, end=self.end) + + def undo(self): + self.screen.clear_clipboard() + self.screen.text = self.previous_state + +class PasteCommand(ScreenCommand): + def __init__(self, screen, offset=0): + super().__init__(screen) + self.offset = offset + + def execute(self): + self.screen.paste(offset= self.offset) + + def undo(self): + self.screen.clear_clipboard() + self.screen.text = self.previous_state + +# Invoker +class ScreenInvoker(object): + def __init__(self): + self.history = [] + + def store_and_execute(self, command): + command.execute() + self.history.append(command) + + def undo_last(self): + if self.history: + self.history.pop().undo() + +if __name__ == '__main__': + screen = Screen('Design Patterns!') + print("Original Text: ",screen) + cut = CutCommand(screen, start=7, end=15 ) + client = ScreenInvoker() + client.store_and_execute(cut) + print("After Cut : ",screen) + + paste = PasteCommand(screen, offset=0) + client.store_and_execute(paste) + print("After Paste : ",screen) + + client.undo_last() + print("Undo Once : ",screen) + + client.undo_last() + print("Undo Twice : ",screen) \ No newline at end of file diff --git a/design-patterns/Command-Python/readme.md b/design-patterns/Command-Python/readme.md new file mode 100644 index 0000000..f66e2e7 --- /dev/null +++ b/design-patterns/Command-Python/readme.md @@ -0,0 +1,17 @@ +# Command Method + +The main goal of this design pattern is to decouple the object that invokes the operation from the other object that knows how to perform it. +This can be done by encapsulating the command from the client as an object.This transformation lets you parameterize methods with different requests, delay or queue a request’s execution The command object knows about a receiver object that manages its internal state when the command is executed. Finally the invoker objects are used to execute the commands. + +![UML diagram for Command Pattern](command.png "UML class diagram of Command") + +# Command Method Example :- +In the given example the command pattern is used to track the history of various operations performed on a digital clipboard by the client.Here receiver object is a screen which have the attributes screen and clipboard. Various operations like cut,paste,clear_cliboard and length of the text can be performed on the clipboard. The screen(receiver) manages the internal state of the object which seperates from the ScreenInvoker object which invokes various commands from the client. In this way the invoker object is decoupled from the receiver object which performs the underlying functionality. The screen comand interface is used to parameterize methods to execute,delay or undo a command. + +# Command Design Pattern Output: + +Original Text: Design Patterns! +After Cut : Design ! +After Paste : PatternsDesign ! +Undo Once : Design ! +Undo Twice : Design Patterns! \ No newline at end of file diff --git a/design-patterns/Iterator-Python/iterator.png b/design-patterns/Iterator-Python/iterator.png new file mode 100644 index 0000000..60d92c1 Binary files /dev/null and b/design-patterns/Iterator-Python/iterator.png differ diff --git a/design-patterns/Iterator-Python/iterator.py b/design-patterns/Iterator-Python/iterator.py new file mode 100644 index 0000000..cfab51e --- /dev/null +++ b/design-patterns/Iterator-Python/iterator.py @@ -0,0 +1,111 @@ +class OddNumbers(object): + "An iterable object." + + def __init__(self, maximum): + self.maximum = maximum + + def __iter__(self): + return OddIterator(self) + +class EvenNumbers(object): + "An iterable object." + + def __init__(self, maximum): + self.maximum = maximum + + def __iter__(self): + return EvenIterator(self) + +class FibnocciNumbers(object): + "An iterable object." + + def __init__(self, maximum): + self.maximum = maximum + + def __iter__(self): + return FibnocciIterator(self) + + + +class OddIterator(object): + "An iterator." + + def __init__(self, container): + self.container = container + self.n = -1 + + def __next__(self): + self.n += 2 + if self.n > self.container.maximum: + raise StopIteration + return self.n + + def __iter__(self): + return self + +class EvenIterator(object): + "An iterator." + + def __init__(self, container): + self.container = container + self.n = 0 + + def __next__(self): + self.n += 2 + if self.n > self.container.maximum: + raise StopIteration + return self.n + + def __iter__(self): + return self + +class FibnocciIterator(object): + "An iterator." + + def __init__(self, container): + self.container = container + self.a = 0 + self.b = 1 + + def __next__(self): + self.a ,self.b = self.b,self.a + self.b + if self.a > self.container.maximum or self.b > self.container.maximum: + raise StopIteration + return self.b + + def __iter__(self): + return self + +def spanish_count_to(count): + """ Built in iterator implementation""" + + numbers_in_Spanish = ["uno, dos, tres, cuatro, cinco, seis, siete, ocho, nueve, diez"] + + #built-in iterator + #Creates a tuple such as (1, "uno") + iterator = zip(range(count), numbers_in_Spanish) + + #Iterate through our iterable list + #Extract the Spanish numbers + #Put them in a generator called number + for position, number in iterator: + + #Returns a 'generator' containing numbers in Spanish + yield number + +numbers = OddNumbers(12) +even = EvenNumbers(16) +fib = FibnocciNumbers(40) + + +print("Fibnocci Iterator :",list(fib)) +print("Odd Iterator :",list(numbers)) +print("Even Iterator(> 4) : ",set(n for n in even if n > 4)) + +for num in spanish_count_to(3): + print("Spanish Numbers Iterator : [{}]".format(num)) + + + + + diff --git a/design-patterns/Iterator-Python/readme.md b/design-patterns/Iterator-Python/readme.md new file mode 100644 index 0000000..624c6ce --- /dev/null +++ b/design-patterns/Iterator-Python/readme.md @@ -0,0 +1,30 @@ +# Iterator + +""" +The main goal of this pattern is to provide a way to access the elements of an aggregate objects(list,stack,tree) sequentially +without exposing its underlying representation and put it in an iterator object. +We can add more than one traversing method(eg- Both DFS and BFS for trees) for the same aggregate object through iterator design pattern. +Using this design pattern we can traverse through any underlying datastructure used to represent objects. +Iterator pattern is not only about traversing through a collection, we can provide different kind of iterators based on our requirements. +One of the fundamental features is that it should allow a client to iterate through a collection, without any knowledge about the implementation of that collection. + +![UML diagram for Iterator Pattern](iterator.png "UML class diagram of Iterator") + +# Example:- +The example lists some of the iterators used to traverse respective aggregate objects. +In the example Fibnocci numbers,odd numbers,spanish numbers are aggregating objects. Fibnocci iterator,odd iterator and spanish_count_to iterators are the concrete iterators that traverse through the list of integers and also implement the iterator interface. +In this way different iterators can be used for different pursposes to traverse through the same underlying object. +In python- +__iter__ method takes a container object as its argument and returns a new iterator object.(Fibnocci iterator,spanish number iterator.. in this case) +__next__ method takes the iterator as its argument and each time it is called, returns the next integer from the container. +Along with these "maximum" atrribute is used to limit the scope of the iterator. In this way the iterators created from the respective aggregate objects are used to traverse elements without the need for the client to know the underlying functionality. + + + +# Iterator design pattern Output: + +Fibnocci Iterator : [1, 2, 3, 5, 8, 13, 21, 34] +Odd Iterator : [1, 3, 5, 7, 9, 11] +Even Iterator(> 4) : {6, 8, 10, 12, 14, 16} +Spanish Numbers Iterator : [uno, dos, tres, cuatro, cinco, seis, siete, ocho, nueve, diez] + diff --git a/design-patterns/State-Python/readme.md b/design-patterns/State-Python/readme.md new file mode 100644 index 0000000..3df29a0 --- /dev/null +++ b/design-patterns/State-Python/readme.md @@ -0,0 +1,18 @@ +# State Design Pattern + +State Pattern allow an object to alter its behavior when its internal state changes. +The object will appear to change its class.The state pattern is used in computer programming to encapsulate varying behavior for the same object, based on its internal state.It also follows - adding new states should not affect the behavior of existing states. +The State pattern lets you reduce code duplication by extracting common code into abstract base classes. +Cons- Applying the pattern can be draining memory if a state machine has only a few states or rarely changes. + +![UML diagram for State Pattern](state.png "UML class diagram of State") + +# Example:- +In this example, the State pattern lets the virtual machine change its state differently, depending on if the state requested to switch is present in allowed list.VirtualMachine_State is the interface for encapsulating the behavior associated with a particular state of the virtual machine. All the other subclasses like shut_down,hibernate,power_on implement a behavior associated with a state of the VM. The VirtualMachine_ class is present to change the current state of the virtual machine object based on the different states(shut_down,hibernate,power_on) passed to it. + +# State Design Pattern Output: +Present State: Shut_down -> State is changed to - Power_On +Present State: Power_On -> State is changed to - Sleep_Mode +Present State: Sleep_Mode -> State change to hibernate not possible. +Present State: Sleep_Mode -> State is changed to - Power_On +Present State: Power_On -> State is changed to - Shut_down \ No newline at end of file diff --git a/design-patterns/State-Python/state.png b/design-patterns/State-Python/state.png new file mode 100644 index 0000000..7bdcea7 Binary files /dev/null and b/design-patterns/State-Python/state.png differ diff --git a/design-patterns/State-Python/state.py b/design-patterns/State-Python/state.py new file mode 100644 index 0000000..cd7c123 --- /dev/null +++ b/design-patterns/State-Python/state.py @@ -0,0 +1,50 @@ +# Base state class +class VirtualMachine_State(object): + name = 'state' + allowed = [] + + def switch(self, state): + """ Switch to new state """ + if state.name in self.allowed: + print('Present State: %s -> State is changed to - %s' %(self, state.name)) + self.__class__ = state + else: + print('Present State: %s -> State change to %s not possible.' + %(self, state.name)) + + def __str__(self): + return self.name + +class Shut_down(VirtualMachine_State): + name = 'Shut_down' + allowed = ['Power_On'] + +class Power_On(VirtualMachine_State): + name = 'Power_On' + allowed = ['Shut_down', 'Sleep_Mode', 'hibernate'] + +class Sleep_Mode(VirtualMachine_State): + name = 'Sleep_Mode' + allowed = ['Power_On'] + +class Hibernate(VirtualMachine_State): + name = 'hibernate' + allowed = ['Power_On'] + +class VirtualMachine_(object): + def __init__(self): + self.state = Shut_down() + + def change(self, state): + self.state.switch(state) + +if __name__ == '__main__': + + c = VirtualMachine_() + c.change(Power_On) + + c.change(Sleep_Mode) + c.change(Hibernate) + + c.change(Power_On) + c.change(Shut_down) \ No newline at end of file diff --git a/design-patterns/Template-Python/readme.md b/design-patterns/Template-Python/readme.md new file mode 100644 index 0000000..7a0984d --- /dev/null +++ b/design-patterns/Template-Python/readme.md @@ -0,0 +1,27 @@ +# Template Method + +Template method defines the structure of an algorithm in an operation, deferring some +steps to subclasses. It lets subclasses redefine certain steps of an algorithm +without changing the algorithm's structure. +When to use +* To implement the similar parts of an algorithm once and leave it up to subclasses to implement the behavior that can vary from class to class. +* when common behavior among subclasses should be factored and localizedin a common class. +* To control subclasses extensions and avoid code duplication. + +![UML diagram for template Pattern](template.png "UML class diagram of Template") + +# Example :- +This pattern is used for storing various forms of data on the cloud. If the storage capacity is full for respective data, it can'nt be saved. All the forms of data(Movie,game.etc) are stored on the server and accessed the same way(common functionalities) but these data are saved on cloud based on storage space. Since the variation of storage space is checked in the later stages and data is saved and accessed the same way for all items,so template design pattern is used here. Here cloud storage is the abstract template class, Store_Movie and Store_Game are the concrete classes that override the abstract class but not change its structure. + +# Template design pattern Output: + +Requesting to save Data on cloud..... +1. Saved Game on remote server. +2. Ready to Play. +*********************************** +Requesting to save Data on cloud..... +1. Saved Music Album on remote server +2. Ready to Play Album. +*********************************** +Requesting to save Data on cloud..... +Not enough space to save.Purchase more storage space! diff --git a/design-patterns/Template-Python/template.png b/design-patterns/Template-Python/template.png new file mode 100644 index 0000000..4d5fd7d Binary files /dev/null and b/design-patterns/Template-Python/template.png differ diff --git a/design-patterns/Template-Python/template.py b/design-patterns/Template-Python/template.py new file mode 100644 index 0000000..1ec98e7 --- /dev/null +++ b/design-patterns/Template-Python/template.py @@ -0,0 +1,61 @@ +import sys +class CloudStorage(object): + + def upload_data(self, storage_space): + print("Requesting to save Data on cloud.....") + if storage_space > self.storage_capacity: + print("Not enough space to save.Purchase more storage space!") + sys.exit(1) + + + def store_on_Server(self): + pass + + def access_data(self): + pass + + def move_to_cloud(self, storage_space): + self.upload_data(storage_space) + self.store_on_Server() + self.access_data() + +class Store_Movie(CloudStorage): + + def __init__(self): + self.storage_capacity = 3 + + def store_on_Server(self): + print("1. Saved Movie on remote server.") + + def access_data(self): + print("2. Ready to Watch.") + +class Store_Game(CloudStorage): + def __init__(self): + self.storage_capacity = 7 + + def store_on_Server(self): + print("1. Saved Game on remote server.") + + def access_data(self): + print("2. Ready to Play.") + +class Store_MusicAlbum(CloudStorage): + def __init__(self): + self.storage_capacity = 2 + + def store_on_Server(self): + print("1. Saved Music Album on remote server") + + def access_data(self): + print("2. Ready to Play Album.") + +if __name__ == '__main__': + c = Store_Game() + c.move_to_cloud(6) + print("*" * 35) + a = Store_MusicAlbum() + a.move_to_cloud(1) + print("*" * 35) + p = Store_Movie() + p.move_to_cloud(4)