| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1 @@ | |||
| 1 | + __pycache__ | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,35 +3,43 @@ | |||
| 3 | 3 | ||
| 4 | 4 | ||
| 5 | 5 | class Data(object): | |
| 6 | + """ Data Store Class """ | ||
| 6 | 7 | ||
| 7 | 8 | products = { | |
| 8 | 9 | 'milk': {'price': 1.50, 'quantity': 10}, | |
| 9 | 10 | 'eggs': {'price': 0.20, 'quantity': 100}, | |
| 10 | 11 | 'cheese': {'price': 2.00, 'quantity': 10} | |
| 11 | 12 | } | |
| 12 | 13 | ||
| 14 | + def __get__(self, obj, klas): | ||
| 15 | + print ("(Fetching from Data Store)") | ||
| 16 | + return {'products': self.products} | ||
| 17 | + | ||
| 13 | 18 | ||
| 14 | 19 | class BusinessLogic(object): | |
| 15 | 20 | ||
| 16 | - def __init__(self): | ||
| 17 | - self.data = Data() | ||
| 21 | + """ Business logic holding data store instances """ | ||
| 22 | + | ||
| 23 | + data = Data() | ||
| 18 | 24 | ||
| 19 | 25 | def product_list(self): | |
| 20 | - return self.data.products.keys() | ||
| 26 | + return self.data['products'].keys() | ||
| 21 | 27 | ||
| 22 | 28 | def product_information(self, product): | |
| 23 | - return self.data.products.get(product, None) | ||
| 29 | + return self.data['products'].get(product, None) | ||
| 24 | 30 | ||
| 25 | 31 | ||
| 26 | 32 | class Ui(object): | |
| 33 | + """ UI interaction class """ | ||
| 27 | 34 | ||
| 28 | 35 | def __init__(self): | |
| 29 | 36 | self.business_logic = BusinessLogic() | |
| 30 | 37 | ||
| 31 | 38 | def get_product_list(self): | |
| 32 | 39 | print('PRODUCT LIST:') | |
| 33 | 40 | for product in self.business_logic.product_list(): | |
| 34 | - print(product) | ||
| 41 | + #print(product) | ||
| 42 | + yield product | ||
| 35 | 43 | print('') | |
| 36 | 44 | ||
| 37 | 45 | def get_product_information(self, product): | |
@@ -56,3 +64,16 @@ def main(): | |||
| 56 | 64 | ||
| 57 | 65 | if __name__ == '__main__': | |
| 58 | 66 | main() | |
| 67 | + | ||
| 68 | + ### OUTPUT ### | ||
| 69 | + # (Fetching from Data Store) | ||
| 70 | + # PRODUCT INFORMATION: | ||
| 71 | + # Name: Cheese, Price: 2.00, Quantity: 10 | ||
| 72 | + # (Fetching from Data Store) | ||
| 73 | + # PRODUCT INFORMATION: | ||
| 74 | + # Name: Eggs, Price: 0.20, Quantity: 100 | ||
| 75 | + # (Fetching from Data Store) | ||
| 76 | + # PRODUCT INFORMATION: | ||
| 77 | + # Name: Milk, Price: 1.50, Quantity: 10 | ||
| 78 | + # (Fetching from Data Store) | ||
| 79 | + # That product "arepas" does not exist in the records | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,34 +1,41 @@ | |||
| 1 | 1 | python-patterns | |
| 2 | 2 | =============== | |
| 3 | 3 | ||
| 4 | - A collection of design patterns implemented (by other people) in python | ||
| 4 | + A collection of design patterns and idioms in Python. | ||
| 5 | + | ||
| 6 | + When an implementation is added or modified, be sure to update this file and | ||
| 7 | + rerun `append_output.sh` (eg. ./append_output.sh borg.py) to keep the output | ||
| 8 | + comments at the bottom up to date. | ||
| 5 | 9 | ||
| 6 | 10 | Current Patterns: | |
| 7 | 11 | ||
| 8 | - * 3-tier | ||
| 9 | - * composite | ||
| 10 | - * mvc | ||
| 11 | - * decorator | ||
| 12 | - * null | ||
| 13 | - * facade | ||
| 14 | - * observer | ||
| 15 | - * abstract_factory | ||
| 16 | - * factory_method | ||
| 17 | - * pool | ||
| 18 | - * adapter | ||
| 19 | - * flyweight | ||
| 20 | - * prototype | ||
| 21 | - * borg | ||
| 22 | - * proxy | ||
| 23 | - * bridge | ||
| 24 | - * graph_search | ||
| 25 | - * state | ||
| 26 | - * builder | ||
| 27 | - * iterator | ||
| 28 | - * strategy | ||
| 29 | - * chain | ||
| 30 | - * mediator | ||
| 31 | - * template | ||
| 32 | - * command | ||
| 33 | - * memento | ||
| 34 | - * visitor | ||
| 12 | + | Pattern | Description | | ||
| 13 | + |:-------:| ----------- | | ||
| 14 | + | [3-tier](3-tier.py) | data<->business logic<->presentation separation (strict relationships) | | ||
| 15 | + | [abstract_factory](abstract_factory.py) | use a generic function with specific factories | | ||
| 16 | + | [adapter](adapter.py) | adapt one interface to another using a whitelist | | ||
| 17 | + | [borg](borg.py) | a singleton with shared-state among instances | | ||
| 18 | + | [bridge](bridge.py) | a client-provider middleman to soften interface changes | | ||
| 19 | + | [builder](builder.py) | call many little discrete methods rather than having a huge number of constructor parameters | | ||
| 20 | + | [catalog](catalog.py) | general methods will call different specialized methods based on construction parameter | | ||
| 21 | + | [chain](chain.py) | apply a chain of successive handlers to try and process the data | | ||
| 22 | + | [command](command.py) | bundle a command and arguments to call later | | ||
| 23 | + | [composite](composite.py) | encapsulate and provide access to a number of different objects | | ||
| 24 | + | [decorator](decorator.py) | wrap functionality with other functionality in order to affect outputs | | ||
| 25 | + | [facade](facade.py) | use one class as an API to a number of others | | ||
| 26 | + | [factory_method](factory_method.py) | delegate a specialized function/method to create instances | | ||
| 27 | + | [flyweight](flyweight.py) | transparently reuse existing instances of objects with similar/identical state | | ||
| 28 | + | [graph_search](graph_search.py) | (graphing algorithms, not design patterns) | | ||
| 29 | + | [mediator](mediator.py) | an object that knows how to connect other objects and act as a proxy | | ||
| 30 | + | [memento](memento.py) | generate an opaque token that can be used to go back to a previous state | | ||
| 31 | + | [mvc](mvc.py) | model<->view<->controller (non-strict relationships) | | ||
| 32 | + | [observer](observer.py) | provide a callback for notification of events/changes to data | | ||
| 33 | + | [pool](pool.py) | preinstantiate and maintain a group of instances of the same type | | ||
| 34 | + | [prototype](prototype.py) | use a factory and clones of a prototype for new instances (if instantiation is expensive) | | ||
| 35 | + | [proxy](proxy.py) | an object funnels operations to something else | | ||
| 36 | + | [publish_subscribe](publish_subscribe.py) | a source syndicates events/data to 0+ registered listeners | | ||
| 37 | + | [state](state.py) | logic is org'd into a discrete number of potential states and the next state that can be transitioned to | | ||
| 38 | + | [strategy](strategy.py) | selectable operations over the same data | | ||
| 39 | + | [template](template.py) | an object imposes a structure but takes pluggable components | | ||
| 40 | + | [visitor](visitor.py) | invoke a callback for all items of a collection | | ||
| 41 | + | [chaining_method](chaining_method.py) | continue callback next object method | | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,32 +1,34 @@ | |||
| 1 | + #!/usr/bin/env python | ||
| 2 | + # -*- coding: utf-8 -*- | ||
| 3 | + | ||
| 1 | 4 | # http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/ | |
| 2 | 5 | ||
| 3 | 6 | """Implementation of the abstract factory pattern""" | |
| 4 | 7 | ||
| 5 | 8 | import random | |
| 6 | 9 | ||
| 7 | - | ||
| 8 | 10 | class PetShop: | |
| 11 | + | ||
| 9 | 12 | """A pet shop""" | |
| 10 | 13 | ||
| 11 | 14 | def __init__(self, animal_factory=None): | |
| 12 | - """pet_factory is our abstract factory. | ||
| 13 | - We can set it at will.""" | ||
| 15 | + """pet_factory is our abstract factory. We can set it at will.""" | ||
| 14 | 16 | ||
| 15 | 17 | self.pet_factory = animal_factory | |
| 16 | 18 | ||
| 17 | 19 | def show_pet(self): | |
| 18 | - """Creates and shows a pet using the | ||
| 19 | - abstract factory""" | ||
| 20 | + """Creates and shows a pet using the abstract factory""" | ||
| 20 | 21 | ||
| 21 | 22 | pet = self.pet_factory.get_pet() | |
| 22 | - print("This is a lovely {}".format(pet)) | ||
| 23 | + print("We have a lovely {}".format(pet)) | ||
| 23 | 24 | print("It says {}".format(pet.speak())) | |
| 24 | - print("It eats {}".format(self.pet_factory.get_food())) | ||
| 25 | + print("We also have {}".format(self.pet_factory.get_food())) | ||
| 25 | 26 | ||
| 26 | 27 | ||
| 27 | 28 | # Stuff that our factory makes | |
| 28 | 29 | ||
| 29 | 30 | class Dog: | |
| 31 | + | ||
| 30 | 32 | def speak(self): | |
| 31 | 33 | return "woof" | |
| 32 | 34 | ||
@@ -35,6 +37,7 @@ def __str__(self): | |||
| 35 | 37 | ||
| 36 | 38 | ||
| 37 | 39 | class Cat: | |
| 40 | + | ||
| 38 | 41 | def speak(self): | |
| 39 | 42 | return "meow" | |
| 40 | 43 | ||
@@ -45,6 +48,7 @@ def __str__(self): | |||
| 45 | 48 | # Factory classes | |
| 46 | 49 | ||
| 47 | 50 | class DogFactory: | |
| 51 | + | ||
| 48 | 52 | def get_pet(self): | |
| 49 | 53 | return Dog() | |
| 50 | 54 | ||
@@ -53,13 +57,13 @@ def get_food(self): | |||
| 53 | 57 | ||
| 54 | 58 | ||
| 55 | 59 | class CatFactory: | |
| 60 | + | ||
| 56 | 61 | def get_pet(self): | |
| 57 | 62 | return Cat() | |
| 58 | 63 | ||
| 59 | 64 | def get_food(self): | |
| 60 | 65 | return "cat food" | |
| 61 | 66 | ||
| 62 | - | ||
| 63 | 67 | # Create the proper family | |
| 64 | 68 | def get_factory(): | |
| 65 | 69 | """Let's be dynamic!""" | |
@@ -68,8 +72,21 @@ def get_factory(): | |||
| 68 | 72 | ||
| 69 | 73 | # Show pets with various factories | |
| 70 | 74 | if __name__ == "__main__": | |
| 71 | - shop = PetShop() | ||
| 72 | 75 | for i in range(3): | |
| 73 | - shop.pet_factory = get_factory() | ||
| 76 | + shop = PetShop(get_factory()) | ||
| 74 | 77 | shop.show_pet() | |
| 75 | 78 | print("=" * 20) | |
| 79 | + | ||
| 80 | + ### OUTPUT ### | ||
| 81 | + # We have a lovely Dog | ||
| 82 | + # It says woof | ||
| 83 | + # We also have dog food | ||
| 84 | + # ==================== | ||
| 85 | + # We have a lovely Dog | ||
| 86 | + # It says woof | ||
| 87 | + # We also have dog food | ||
| 88 | + # ==================== | ||
| 89 | + # We have a lovely Cat | ||
| 90 | + # It says meow | ||
| 91 | + # We also have cat food | ||
| 92 | + # ==================== | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,41 +1,38 @@ | |||
| 1 | - # http://ginstrom.com/scribbles/2008/11/06/generic-adapter-class-in-python/ | ||
| 1 | + #!/usr/bin/env python | ||
| 2 | + # -*- coding: utf-8 -*- | ||
| 2 | 3 | ||
| 3 | - import os | ||
| 4 | + """http://ginstrom.com/scribbles/2008/11/06/generic-adapter-class-in-python/""" | ||
| 4 | 5 | ||
| 6 | + import os | ||
| 5 | 7 | ||
| 6 | 8 | class Dog(object): | |
| 7 | 9 | def __init__(self): | |
| 8 | 10 | self.name = "Dog" | |
| 9 | - | ||
| 10 | 11 | def bark(self): | |
| 11 | 12 | return "woof!" | |
| 12 | 13 | ||
| 13 | - | ||
| 14 | 14 | class Cat(object): | |
| 15 | 15 | def __init__(self): | |
| 16 | 16 | self.name = "Cat" | |
| 17 | - | ||
| 18 | 17 | def meow(self): | |
| 19 | 18 | return "meow!" | |
| 20 | 19 | ||
| 21 | - | ||
| 22 | 20 | class Human(object): | |
| 23 | 21 | def __init__(self): | |
| 24 | 22 | self.name = "Human" | |
| 25 | - | ||
| 26 | 23 | def speak(self): | |
| 27 | 24 | return "'hello'" | |
| 28 | 25 | ||
| 29 | 26 | ||
| 30 | 27 | class Car(object): | |
| 31 | 28 | def __init__(self): | |
| 32 | 29 | self.name = "Car" | |
| 33 | - | ||
| 34 | 30 | def make_noise(self, octane_level): | |
| 35 | 31 | return "vroom{0}".format("!" * octane_level) | |
| 36 | 32 | ||
| 37 | 33 | ||
| 38 | 34 | class Adapter(object): | |
| 35 | + | ||
| 39 | 36 | """ | |
| 40 | 37 | Adapts an object by replacing methods. | |
| 41 | 38 | Usage: | |
@@ -60,6 +57,7 @@ class Adapter(object): | |||
| 60 | 57 | A Human goes 'hello' | |
| 61 | 58 | A Car goes vroom!!! | |
| 62 | 59 | """ | |
| 60 | + | ||
| 63 | 61 | def __init__(self, obj, adapted_methods): | |
| 64 | 62 | """We set the adapted methods in the object's dict""" | |
| 65 | 63 | self.obj = obj | |
@@ -86,5 +84,10 @@ def main(): | |||
| 86 | 84 | ||
| 87 | 85 | ||
| 88 | 86 | if __name__ == "__main__": | |
| 89 | - import doctest | ||
| 90 | - doctest.testmod() | ||
| 87 | + main() | ||
| 88 | + | ||
| 89 | + ### OUTPUT ### | ||
| 90 | + # A Dog goes woof! | ||
| 91 | + # A Cat goes meow! | ||
| 92 | + # A Human goes 'hello' | ||
| 93 | + # A Car goes vroom!!! | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,12 @@ | |||
| 1 | + #!/bin/bash | ||
| 2 | + | ||
| 3 | + set -e | ||
| 4 | + | ||
| 5 | + src=$(sed -n -e '/### OUTPUT ###/,$!p' "$1") | ||
| 6 | + output=$(python "$1" | sed 's/^/# /') | ||
| 7 | + | ||
| 8 | + # These are done separately to avoid having to insert a newline, which causes | ||
| 9 | + # problems when the text itself has '\n' in strings | ||
| 10 | + echo "$src" > $1 | ||
| 11 | + echo -e "\n### OUTPUT ###" >> $1 | ||
| 12 | + echo "$output" >> $1 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,8 +1,13 @@ | |||
| 1 | + #!/usr/bin/env python | ||
| 2 | + # -*- coding: utf-8 -*- | ||
| 3 | + | ||
| 4 | + | ||
| 1 | 5 | class Borg: | |
| 2 | 6 | __shared_state = {} | |
| 3 | 7 | ||
| 4 | 8 | def __init__(self): | |
| 5 | 9 | self.__dict__ = self.__shared_state | |
| 10 | + self.state = 'Init' | ||
| 6 | 11 | ||
| 7 | 12 | def __str__(self): | |
| 8 | 13 | return self.state | |
@@ -18,19 +23,30 @@ class YourBorg(Borg): | |||
| 18 | 23 | rm1.state = 'Idle' | |
| 19 | 24 | rm2.state = 'Running' | |
| 20 | 25 | ||
| 21 | - print('rm1:', rm1) | ||
| 22 | - print('rm2:', rm2) | ||
| 26 | + print('rm1: {0}'.format(rm1)) | ||
| 27 | + print('rm2: {0}'.format(rm2)) | ||
| 23 | 28 | ||
| 24 | 29 | rm2.state = 'Zombie' | |
| 25 | 30 | ||
| 26 | - print('rm1:', rm1) | ||
| 27 | - print('rm2:', rm2) | ||
| 31 | + print('rm1: {0}'.format(rm1)) | ||
| 32 | + print('rm2: {0}'.format(rm2)) | ||
| 28 | 33 | ||
| 29 | - print('rm1 id:', id(rm1)) | ||
| 30 | - print('rm2 id:', id(rm2)) | ||
| 34 | + print('rm1 id: {0}'.format(id(rm1))) | ||
| 35 | + print('rm2 id: {0}'.format(id(rm2))) | ||
| 31 | 36 | ||
| 32 | 37 | rm3 = YourBorg() | |
| 33 | 38 | ||
| 34 | - print('rm1:', rm1) | ||
| 35 | - print('rm2:', rm2) | ||
| 36 | - print('rm3:', rm3) | ||
| 39 | + print('rm1: {0}'.format(rm1)) | ||
| 40 | + print('rm2: {0}'.format(rm2)) | ||
| 41 | + print('rm3: {0}'.format(rm3)) | ||
| 42 | + | ||
| 43 | + ### OUTPUT ### | ||
| 44 | + # rm1: Running | ||
| 45 | + # rm2: Running | ||
| 46 | + # rm1: Zombie | ||
| 47 | + # rm2: Zombie | ||
| 48 | + # rm1 id: 140732837899224 | ||
| 49 | + # rm2 id: 140732837899296 | ||
| 50 | + # rm1: Init | ||
| 51 | + # rm2: Init | ||
| 52 | + # rm3: Init | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments