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
23 changed files
with
832 additions
and
533 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 |
---|---|---|
@@ -1,61 +1,65 @@ | ||
class Klass1: | ||
""" a very simple obj """ | ||
def __init__(self): | ||
pass | ||
def hi(self): | ||
print 'hi' | ||
|
||
class Factory: | ||
""" base factory that can construct objects in a variety of ways: | ||
* modules ['package1.subpackage',] to be searched for klass | ||
* search global namespace | ||
* create takes a arguement of what type of class to return | ||
* return a default implementation - subclass must define createDefault() | ||
""" | ||
def __init__(self, modules=[]): | ||
self.modules=modules | ||
|
||
def createDefault(self): | ||
print dir() | ||
raise NotImplementedError | ||
|
||
def create(self, klass=None): | ||
import string | ||
if klass in globals().keys(): | ||
if type(globals()[klass]).__name__=='class': | ||
return globals()[klass]() | ||
for module in self.modules: | ||
try: | ||
fromlist = [] | ||
if string.find(module, '.'): fromlist = string.split(module, '.')[:-1] | ||
module = __import__(module, globals(), locals(), fromlist) | ||
if hasattr(module, klass): return getattr(module, klass)() | ||
except AttributeError: pass | ||
return self.createDefault() | ||
|
||
class MyFactory(Factory): | ||
""" concrete factory that specifies: | ||
* what modules to search for | ||
* implements a createDefault() - which is used if class isnt found | ||
""" | ||
def __init__(self, modules=[]): | ||
Factory.__init__(self,modules) | ||
def createDefault(self): | ||
return Klass1() | ||
|
||
|
||
#--------much simpler one by mark lutz, http://shell.rmi.net/~lutz/talk.html | ||
def factory(aClass, *args): # varargs tuple | ||
return apply(aClass, args) # call aClass | ||
|
||
class Spam: | ||
def doit(self, message): | ||
print message | ||
|
||
class Person: | ||
def __init__(self, name, job): | ||
self.name = name | ||
self.job = job | ||
|
||
object1 = factory(Spam) | ||
object2 = factory(Person, "Guido", "guru") | ||
"""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 |
---|---|---|
@@ -1,20 +1,25 @@ | ||
class Barfooer: | ||
def barfoo(self, bar, foo): | ||
pass | ||
class Adaptee: | ||
def specific_request(self): | ||
return 'Adaptee' | ||
|
||
# Per instance, by wrapping and delegation | ||
class FoobaringWrapper: | ||
def __init__(self, wrappee): | ||
self.w = wrappee | ||
def foobar(self, foo, bar): | ||
return self.w.barfoo(bar, foo) | ||
class Adapter: | ||
def __init__(self, adaptee): | ||
self.adaptee = adaptee | ||
|
||
foobarer = FoobaringWrapper(barfooer) | ||
def request(self): | ||
return self.adaptee.specific_request() | ||
|
||
# Per-classs by subclassing and self-delegation | ||
class Foobarer(Barfooer): | ||
def foobar(self,foo, bar): | ||
return self.barfoo(bar, foo) | ||
client = Adapter(Adaptee()) | ||
print client.request() | ||
|
||
foobarer = Foobarer(some, init, params) | ||
# --------- Second example (by Alex Martelli)------------ | ||
|
||
class UppercasingFile: | ||
def __init__(self, *a, **k): | ||
self.f = file(*a, **k) | ||
|
||
def write(self, data): | ||
self.f.write(data.upper()) | ||
|
||
def __getattr__(self, name): | ||
return getattr(self.f, name) |
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 |
---|---|---|
@@ -1,9 +1,60 @@ | ||
class AbstractParser: | ||
def __init__(self, scanner): | ||
self.scanner = scanner | ||
|
||
class ExprParser(AbstractParser): | ||
def expr(self): | ||
t = self.scanner.next()... | ||
self.scanner.push_back(t)... | ||
|
||
# Implementor | ||
class DrawingAPI: | ||
def drawCircle(x, y, radius): | ||
pass | ||
|
||
|
||
# ConcreteImplementor 1/2 | ||
class DrawingAPI1(DrawingAPI): | ||
def drawCircle(self, x, y, radius): | ||
print "API1.circle at %f:%f radius %f" % (x, y, radius) | ||
|
||
|
||
# ConcreteImplementor 2/2 | ||
class DrawingAPI2(DrawingAPI): | ||
def drawCircle(self, x, y, radius): | ||
print "API2.circle at %f:%f radius %f" % (x, y, radius) | ||
|
||
|
||
# Abstraction | ||
class Shape: | ||
# Low-level | ||
def draw(self): | ||
pass | ||
|
||
# High-level | ||
def resizeByPercentage(self, pct): | ||
pass | ||
|
||
|
||
# Refined Abstraction | ||
class CircleShape(Shape): | ||
def __init__(self, x, y, radius, drawingAPI): | ||
self.__x = x | ||
self.__y = y | ||
self.__radius = radius | ||
self.__drawingAPI = drawingAPI | ||
|
||
# low-level i.e. Implementation specific | ||
def draw(self): | ||
self.__drawingAPI.drawCircle(self.__x, self.__y, self.__radius) | ||
|
||
# high-level i.e. Abstraction specific | ||
def resizeByPercentage(self, pct): | ||
self.__radius *= pct | ||
|
||
|
||
def main(): | ||
shapes = [ | ||
CircleShape(1, 2, 3, DrawingAPI1()), | ||
CircleShape(5, 7, 11, DrawingAPI2()) | ||
] | ||
|
||
for shape in shapes: | ||
shape.resizeByPercentage(2.5) | ||
shape.draw() | ||
|
||
if __name__ == "__main__": | ||
main() |
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,44 @@ | ||
class Car: | ||
def __init__(self): | ||
self.name = None | ||
self.km = 11100 | ||
self.fuel = 5 | ||
self.oil = 5 | ||
|
||
|
||
def handle_fuel(car): | ||
if car.fuel < 10: | ||
print "added fuel" | ||
car.fuel = 100 | ||
|
||
|
||
def handle_km(car): | ||
if car.km > 10000: | ||
print "made a car test." | ||
car.km = 0 | ||
|
||
|
||
def handle_oil(car): | ||
if car.oil < 10: | ||
print "Added oil" | ||
car.oil = 100 | ||
|
||
|
||
class Garage: | ||
def __init__(self): | ||
self.handlers = [] | ||
|
||
def add_handler(self, handler): | ||
self.handlers.append(handler) | ||
|
||
def handle_car(self, car): | ||
for handler in self.handlers: | ||
handler(car) | ||
|
||
if __name__ == '__main__': | ||
handlers = [handle_fuel, handle_km, handle_oil] | ||
garage = Garage() | ||
|
||
for handle in handlers: | ||
garage.add_handler(handle) | ||
garage.handle_car(Car()) |
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
Oops, something went wrong.