forked from gennad/Design-Patterns-in-Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
"""Implementation of the abstract factory pattern""" | ||
|
||
import random | ||
|
||
class PetShop: | ||
"""A pet shop""" | ||
|
||
def __init__(self, animal_factory=None): | ||
"""pet_factory is our abstract factory. | ||
We can set it at will.""" | ||
|
||
self.pet_factory = animal_factory | ||
|
||
def show_pet(self): | ||
"""Creates and shows a pet using the | ||
abstract factory""" | ||
|
||
pet = self.pet_factory.get_pet() | ||
print "This is a lovely", pet | ||
print "It says", pet.speak() | ||
print "It eats", self.pet_factory.get_food() | ||
|
||
# Stuff that our factory makes | ||
|
||
class Dog: | ||
def speak(self): | ||
return "woof" | ||
def __str__(self): | ||
return "Dog" | ||
|
||
class Cat: | ||
def speak(self): | ||
return "meow" | ||
def __str__(self): | ||
return "Cat" | ||
|
||
# Factory classes | ||
|
||
class DogFactory: | ||
def get_pet(self): | ||
return Dog() | ||
def get_food(self): | ||
return "dog food" | ||
|
||
class CatFactory: | ||
def get_pet(self): | ||
return Cat() | ||
def get_food(self): | ||
return "cat food" | ||
|
||
# Create the proper family | ||
def get_factory(): | ||
"""Let's be dynamic!""" | ||
return random.choice([DogFactory, CatFactory])() | ||
|
||
# Show pets with various factories | ||
shop = PetShop() | ||
for i in range(3): | ||
shop.pet_factory = get_factory() | ||
shop.show_pet() | ||
print "=" * 10 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
def Dx(f, dx): | ||
def dfdx(x): | ||
return (f(x + dx) - f(x))/dx | ||
return dfdx | ||
|
||
def f(x): | ||
return 3*x**2+x | ||
|
||
""" | ||
>>> print f(1.0) | ||
4.0 | ||
>>> print Dx(f, 0.01)(1.0) | ||
7.03 | ||
>>> print Dx(Dx(f, 0.01), 0.01)(1.0) | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import time | ||
|
||
def time_this(func): | ||
"""The time_this decorator""" | ||
|
||
def decorated(*args, **kwargs): | ||
start = time.time() | ||
result = func(*args, **kwargs) | ||
print "Ran in", time.time() – start, "seconds" | ||
return result | ||
return decorated | ||
|
||
# Decorator syntax | ||
@time_this | ||
def count(until): | ||
"""Counts to 'until', then returns the result""" | ||
|
||
print "Counting to", until, "…" | ||
num = 0 | ||
for i in xrange(to_num(until)): | ||
num += 1 | ||
return num | ||
|
||
def to_num(numstr): | ||
"""Turns a comma-separated number string to an int""" | ||
return int(numstr.replace(",", "")) | ||
|
||
# Run count with various values | ||
for number in ("10,000", "100,000", "1,000,000"): | ||
print count(number) | ||
print "-" * 20 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
def notify(f): | ||
def g(self, n): | ||
print n | ||
return f(self, n) | ||
return g | ||
|
||
class Point(object): | ||
def __init__(self, x, y): | ||
self.x = x | ||
self.y = y | ||
|
||
@notify | ||
def scale(self, n): | ||
self.x = n * self.x | ||
self.y = n * self.y | ||
|
||
p = Point(2.0, 3.0) | ||
p.scale(2.5) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#coding: UTF8 | ||
|
||
class JapaneseGetter: | ||
"""A simple localizer a la gettext""" | ||
|
||
def __init__(self): | ||
self.trans = dict(dog="犬", cat="猫") | ||
|
||
def get(self, msgid): | ||
"""We'll punt if we don't have a translation""" | ||
|
||
try: | ||
return unicode(self.trans[msgid], "utf-8") | ||
except KeyError: | ||
return unicode(msgid) | ||
|
||
class EnglishGetter: | ||
"""Simply echoes the msg ids""" | ||
def get(self, msgid): | ||
return unicode(msgid) | ||
|
||
def get_localizer(language="English"): | ||
"""The factory method""" | ||
|
||
languages = dict(English=EnglishGetter, | ||
Japanese=JapaneseGetter) | ||
|
||
return languages[language]() | ||
|
||
# Create our localizers | ||
e, j = get_localizer("English"), get_localizer("Japanese") | ||
|
||
# Localize some text | ||
for msgid in "dog parrot cat".split(): | ||
print e.get(msgid), j.get(msgid) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class A(object): | ||
def __init__(self): | ||
self.a = "Hello" | ||
|
||
class B(object): | ||
def __init__(self): | ||
self.a = " World" | ||
myfactory = { | ||
"greeting" : A, | ||
"subject" : B, | ||
} | ||
|
||
>>> print myfactory["greeting"]().a | ||
Hello | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
""" | ||
Flyweight Design Pattern | ||
Desc: Sharing the shareable data between the common classes and thus reducing the memory usage | ||
Code: Believing that every person in a family will have same genetic structure, we will create a code to learn about | ||
genetics of each family. If a same member of a family is given, no new object is created. (You can also create new | ||
objects unlike here but keep a reference of the heavy weighted one in the new |||r object). | ||
""" | ||
|
||
class ComplexGenetics(object): | ||
""" returns a huge genetic pattern""" | ||
def __init__(self): | ||
pass | ||
|
||
def genes(self, gene_code): | ||
return "ComplexPatter[%s]TooHugeinSize" % (gene_code) | ||
|
||
class Families(object): | ||
""" To learn about Family Genetic Pattern """ | ||
family = {} | ||
def __new__(cls, name, family_id): | ||
""" i have to capture the details before the class is created, __init__ is pseudo constructor """ | ||
try: | ||
id = cls.family[family_id] | ||
except KeyError: | ||
id = object.__new__(cls) | ||
cls.family[family_id] = id | ||
return id | ||
|
||
def set_genetic_info(self, genetic_info): | ||
cg = ComplexGenetics() | ||
self.genetic_info = cg.genes(genetic_info) | ||
|
||
def get_genetic_info(self): | ||
return (self.genetic_info) | ||
|
||
def test(): | ||
# name, family_id and genetic code details (i dont care if genetic code detail varies in same family [it is research fault :-D ]) | ||
data = (('a', 1, 'ATAG'), ('a', 2, 'AAGT'), ('b', 1, 'ATAG')) | ||
family_objects = [] | ||
for i in data: | ||
obj = Families(i[0], i[1]) | ||
obj.set_genetic_info(i[2]) | ||
family_objects.append(obj) | ||
|
||
for i in family_objects: | ||
print "id = " + str(id(i)) | ||
print i.get_genetic_info() | ||
print "similar id's says that they are same objects " | ||
|
||
if __name__ == '__main__': | ||
test() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
"""Implementation of the iterator pattern with a generator""" | ||
|
||
def count_to(count): | ||
"""Counts by word numbers, up to a maximum of five""" | ||
|
||
numbers = ["one", "two", "three", "four", "five"] | ||
# The zip keeps from counting over the limit | ||
for number, pos in zip(numbers, range(count)): | ||
yield number | ||
|
||
# Test the generator | ||
count_to_two = lambda : count_to(2) | ||
count_to_five = lambda : count_to(5) | ||
|
||
print "Counting to two…" | ||
for number in count_to_two(): | ||
print number, | ||
print "\n" | ||
print "Counting to five…" | ||
for number in count_to_five(): | ||
print number, |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
class Point(object): | ||
def __init__(self, x, y): | ||
self.x = x | ||
self.y = y | ||
|
||
def scale(self, n): | ||
self.x = n * self.x | ||
self.y = n * self.y | ||
|
||
def notify(f): | ||
def g(self, n): | ||
print n | ||
return f(self, n) | ||
return g | ||
|
||
Point.scale = notify(Point.scale) | ||
p = Point(2.0, 3.0) | ||
p.scale(2.5) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
"""Implementation of the state pattern""" | ||
|
||
class State(object): | ||
"""Base state. This is to share functionality""" | ||
|
||
def scan(self): | ||
"""Scan the dial to the next station""" | ||
self.pos += 1 | ||
if self.pos == len(self.stations): | ||
self.pos = 0 | ||
print "Scanning… Station is", self.stations[self.pos], self.name | ||
|
||
class AmState(State): | ||
def __init__(self, radio): | ||
self.radio = radio | ||
self.stations = ["1250", "1380", "1510"] | ||
self.pos = 0 | ||
self.name = "AM" | ||
|
||
def toggle_amfm(self): | ||
print "Switching to FM" | ||
self.radio.state = self.radio.fmstate | ||
|
||
class FmState(State): | ||
def __init__(self, radio): | ||
self.radio = radio | ||
self.stations = ["81.3", "89.1", "103.9"] | ||
self.pos = 0 | ||
self.name = "FM" | ||
|
||
def toggle_amfm(self): | ||
print "Switching to AM" | ||
self.radio.state = self.radio.amstate | ||
|
||
class Radio(object): | ||
"""A radio. | ||
It has a scan button, and an AM/FM toggle switch.""" | ||
|
||
def __init__(self): | ||
"""We have an AM state and an FM state""" | ||
|
||
self.amstate = AmState(self) | ||
self.fmstate = FmState(self) | ||
self.state = self.amstate | ||
|
||
def toggle_amfm(self): | ||
self.state.toggle_amfm() | ||
def scan(self): | ||
self.state.scan() | ||
|
||
# Test our radio out | ||
radio = Radio() | ||
actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2 | ||
actions = actions * 2 | ||
for action in actions: | ||
action() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
def bisection(line): | ||
return 5.5, 6.6 | ||
|
||
def conjugate_gradient(line): | ||
return 3.3, 4.4 | ||
|
||
def test(): | ||
solver = conjugate_gradient | ||
print solver((5.5,5.5)) | ||
solver = bisection | ||
print solver((5.5,5.5)) | ||
test() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
"""An example of the Template pattern in Python""" | ||
|
||
# Skeletons | ||
def iter_elements(getter, action): | ||
"""Template skeleton that iterates items""" | ||
|
||
for element in getter(): | ||
action(element) | ||
print "-" * 10 | ||
|
||
def rev_elements(getter, action): | ||
"""Template skeleton that iterates items in reverse order""" | ||
|
||
for element in getter()[::-1]: | ||
action(element) | ||
print "-" * 10 | ||
|
||
# Getters | ||
def get_list(): | ||
return "spam eggs".split() | ||
|
||
def get_lists(): | ||
return [list(x) for x in "spam eggs".split()] | ||
|
||
# Actions | ||
def print_item(item): | ||
print item | ||
|
||
def reverse_item(item): | ||
print item[::-1] | ||
|
||
# Makes templates | ||
def make_template(skeleton, getter, action): | ||
"""Instantiate a template method with getter and action""" | ||
def template(): | ||
skeleton(getter, action) | ||
return template | ||
|
||
# Create our template functions | ||
templates = [make_template(s, g, a) | ||
for g in (get_list, get_lists) | ||
for a in (print_item, reverse_item) | ||
for s in (iter_elements, rev_elements)] | ||
|
||
# Execute them | ||
for template in templates: | ||
template() |