Skip to content

Commit

Permalink
Add more impls in python: abstract-factory, decorator, facade, factor…
Browse files Browse the repository at this point in the history
…y-method, iterator, flyweight, memento, null-object, observer, template
  • Loading branch information
oxnz committed Sep 26, 2013
1 parent fd0d2e2 commit 986b8c8
Show file tree
Hide file tree
Showing 12 changed files with 625 additions and 10 deletions.
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,31 @@ singleton | [DONE](./src/singleton/singleton.md) | [DONE](./src/singleton/cpp) |
proxy | [DONE](./src/proxy/proxy.md) | [DONE](./src/proxy/cpp) | [DONE](./src/proxy/java) | [DONE](./src/proxy/python)
builder | [DONE](./src/builder/builder.md) | [DONE](./src/builder/cpp) | [DONE](./src/builder/java) | [TODO]
command | [DONE](./src/command/command.md) | [DONE](./src/command/cpp) | [DONE](./src/command/java) | [TODO]
decorator | [DONE](./src/decorator/decorator.md) | [DONE](./src/decorator/cpp) | [DONE](./src/decorator/java) | [TODO]
facade | [DONE](./src/facade/facade.md) | [DONE](./src/facade/cpp) | [DONE](./src/facade/java) | [TODO]
observer | [DONE](./src/observer/observer.md) | [DONE](./src/observer/cpp) | [DONE](./src/observer/java) | [TODO]
template | [DONE](./src/template/template.md) | [DONE](./src/template/cpp) | [DONE](./src/template/java) | [TODO]
decorator | [DONE](./src/decorator/decorator.md) | [DONE](./src/decorator/cpp) | [DONE](./src/decorator/java) | [DONE](./src/decorator/python)
facade | [DONE](./src/facade/facade.md) | [DONE](./src/facade/cpp) | [DONE](./src/facade/java) | [DONE](./src/facade/python)
observer | [DONE](./src/observer/observer.md) | [DONE](./src/observer/cpp) | [DONE](./src/observer/java) | [DONE](./src/observer/python)
template | [DONE](./src/template/template.md) | [DONE](./src/template/cpp) | [DONE](./src/template/java) | [DONE](./src/template/python)
adapter | [DONE](./src/adapter/adapter.md) | [DONE](./src/adapter/cpp) | [DONE](./src/adapter/java) | [TODO]
flyweight | [DONE](./src/flyweight/flyweight.md) | [DONE](./src/flyweight/cpp) | [DONE](./src/flyweight/java) | [TODO]
flyweight | [DONE](./src/flyweight/flyweight.md) | [DONE](./src/flyweight/cpp) | [DONE](./src/flyweight/java) | [DONE](./src/flyweight/python)
bridge | [DONE](./src/bridge/bridge.md) | [DONE](./src/bridge/cpp) | [DONE](./src/bridge/java) | [TODO]
composite | [DONE](./src/composite/composite.md) | [DONE](./src/composite/cpp) | [DONE](./src/composite/java) | [TODO]
interpreter | [DONE](./src/interpreter/interpreter.md) | [DONE](./src/interpreter/cpp) | [DONE](./src/interpreter/java) | [TODO]
mediator | [DONE](./src/mediator/mediator.md) | [DONE](./src/mediator/cpp) | [DONE](./src/mediator/java) | [TODO]
memento | [DONE](./src/memento/memento.md) | [DONE](./src/memento/cpp) | [DONE](./src/memento/java) | [TODO]
memento | [DONE](./src/memento/memento.md) | [DONE](./src/memento/cpp) | [DONE](./src/memento/java) | [DONE](./src/memento/python)
state | [DONE](./src/state/state.md) | [DONE](./src/state/cpp) | [DONE](./src/state/java) | [DONE](./src/state/python)
prototype | [DONE](./src/prototype/prototype.md) | [DONE](./src/prototype/cpp) | [DONE](./src/prototype/java) | [TODO]
strategy | [DONE](./src/strategy/strategy.md) | [DONE](./src/strategy/cpp) | [DONE](./src/strategy/java) | [TODO]
visitor | [DONE](./src/visitor/visitor.md) | [DONE](./src/visitor/cpp) | [DONE](./src/visitor/java) | [DONE](./src/visitor/python)
simple-factory | [DONE](./src/simple-factory/simple-factory.md) | [DONE](./src/simple-factory/cpp) | [DONE](./src/simple-factory/java) | [TODO]
abstract-factory | [DONE](./src/abstract-factory/abstract-factory.md) | [DONE](./src/abstract-factory/cpp) | [DONE](./src/abstract-factory/java) | [TODO]
factory-method | [DONE](./src/factory-method/factory-method.md) | [DONE](./src/factory-method/cpp) | [DONE](./src/factory-method/java) | [TODO]
abstract-factory | [DONE](./src/abstract-factory/abstract-factory.md) | [DONE](./src/abstract-factory/cpp) | [DONE](./src/abstract-factory/java) | [DONE](./src/abstract-factory/python)
factory-method | [DONE](./src/factory-method/factory-method.md) | [DONE](./src/factory-method/cpp) | [DONE](./src/factory-method/java) | [DONE](./src/factory-method/python)
chain-of-responsibility | [DONE](./src/chain-of-responsibility/chain-of-responsibility.md) | [DONE](./src/chain-of-responsibility/cpp) | [DONE](./src/chain-of-responsibility/java) | [TODO]
iterator | [TODO] | [TODO] | [TODO] | [TODO]
null-object | [TODO] | [TODO] | [TODO] | [TODO]
iterator | [DONE](./src/iterator/iterator.md) | [DONE](./src/iterator/cpp) | [TODO] | [DONE](./src/iterator/python)
null-object | [DONE](./src/null-object/null-object.md) | [DONE](./src/null-object/cpp) | [TODO] | [DONE](./src/null-object/python)
private-class-data | [TODO] | [TODO] | [TODO] | [TODO]

[PHP](https://github.com/domnikl/DesignPatternsPHP) DONE

##TODO

添加其他语言的实现。
Expand All @@ -49,4 +50,5 @@ finish python implementation
Please feel free to fork and extend existing or add your own examples and send a pull request with your changes!

##License

[the MIT License](./LICENSE)
66 changes: 66 additions & 0 deletions src/abstract-factory/python/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/usr/bin/python
#coding: UTF-8

"""Implementation of the abstract factory pattern"""

from abc import abstractmethod

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 "Pet: %s says [%s] while eating [%s]" % (pet, pet.speak(), self.pet_factory.get_food())

# Stuff that our factory makes

class Pet:
@abstractmethod
def speack(self):
pass
@abstractmethod
def __str__(self):
return ""

class Dog(Pet):
def speak(self):
return "woof!"
def __str__(self):
return "Dog"

class Cat(Pet):
def speak(self):
return "meow~"
def __str__(self):
return "Cat"

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"

# Creates the proper family
def get_factory():
"""Let's be dynamic!"""
import random
return random.choice([DogFactory, CatFactory])()

if __name__ == '__main__':
# Show pets with various factories
shop = PetShop()
for i in range(3):
shop.pet_factory = get_factory()
shop.show_pet()
24 changes: 24 additions & 0 deletions src/decorator/python/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python
#-*- coding: utf-8 -*-

class Foo(object):
def f1(self):
print ("original f1")
def f2(self, x):
print ("original f2: %s") % x

class DecoratedFoo(object):
def __init__(self, decoratee):
self._decoratee = decoratee
def f1(self):
print ("decorated f1")
self._decoratee.f1()
def __getattr__(self, name):
return getattr(self._decoratee, name)

if __name__ == '__main__':
f = Foo()
df = DecoratedFoo(f)
df.f1()
f.f2('x')
df.f2('xyz')
43 changes: 43 additions & 0 deletions src/decorator/python/test2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# coding: utf-8

"""
This one is another gimme — decorators have built-in syntax since Python 2.4 (they're still trivial to implement in earlier versions).
This example shows a time_this decorator, which measures and prints the time it takes the decorated function to run, in seconds.
"""

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):
"""Count 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
def test():
for number in ("10,000", "100,000", "1,000,000"):
print count(number)
print "-" * 20

if __name__ == '__main__':
test()
28 changes: 28 additions & 0 deletions src/facade/python/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#coding: utf-8

class KillVirus:
def operation(self):
print "killing virus"

class ZipFile:
def operation(self):
print "zipping"

class EncryptFile:
def operation(self):
print "encrypting"

# Facade
class Filesys:
def __init__(self):
self._kv = KillVirus()
self._zf = ZipFile()
self._ef = EncryptFile()

def operation(self):
"""Wrapped all details in this function"""
[i.operation() for i in (self._kv, self._zf, self._ef)]

if __name__ == '__main__':
fs = Filesys()
fs.operation()
31 changes: 31 additions & 0 deletions src/factory-method/python/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#coding: utf-8

class EnglishGetter:
'''simple echoes the msg'''
def get(self, msg):
return unicode(msg)

class JapaneseGetter:
'''A simple localizer a la gettext'''

def __init__(self):
self.trans = dict(dog="犬", cat="猫")

def get(self, msg):
'''we'll punt if we don't have a traslation'''
try:
return unicode(self.trans[msg], "utf-8")
except KeyError:
return unicode(msg)

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 msg in "dog parrot cat".split():
print e.get(msg), j.get(msg)
36 changes: 36 additions & 0 deletions src/flyweight/python/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#coding: utf-8

'''http://codesnipers.com/?q=python-flyweights'''

import weakref

class Card(object):
'''The object pool. Has builtin reference counting'''
_CardPool = weakref.WeakValueDictionary()

'''Flyweight implementation.
If the object exists in the pool, just return it(instead of creating
a new one)
'''
def __new__(cls, value, suit):
obj = Card._CardPool.get(value + suit, None)
if not obj:
obj = obj.__new__(cls)
obj.value, obj.suit = value, suit
Card._CardPool[value+suit] = obj
return obj

#def __init__(self, value, suit):
# self.value, self.suit = value, suit

def __repr__(self):
return "<Card: %s %s>" % (self.value, self.suit)

if __name__ == '__main__':
# comment __new__ and uncomment __init__ to see the difference
c1 = Card('9', 'h')
c2 = Card('9', 'h')
print (c1, c2)
print (c1 == c2)
print (id(c1), id(c2))
25 changes: 25 additions & 0 deletions src/iterator/python/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#coding: utf-8
'''Implementation of the iterator pattern with a generator
http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/
'''

def count_to(count):
'''Counts by work 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可以用来为一个函数返回值塞数据'''
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 '\nCounting to five...'
for number in count_to_five():
print number,
print
90 changes: 90 additions & 0 deletions src/memento/python/memento.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env python
#-*- coding: utf-8 -*-

"""
Memento pattern
http://code.activestate.com/recipes/413838-memento-closure/
The memento pattern is great for transaction-like processing. Having a handy implementation around might not be the worst thing.
"""

import copy

def Memento(obj, deep=False):
state = (copy.copy, copy.deepcopy)[bool(deep)](obj.__dict__)
def Restore():
obj.__dict__.clear()
obj.__dict__.update(state)
return Restore

class Transaction:
"""A transaction guard. This is realy just
syntactic suggar arount a memento closure.
"""
deep = False
def __init__(self, *targets):
self.targets = targets
self.Commit()
def Commit(self):
self.states = [Memento(target, self.deep) for target in self.targets]
def Rollback(self):
for state in self.states:
state()

class transactional:
"""Adds transactional semantics to methods. Methods decorated
with @transactional will rollback to entry state upon exceptions.
"""
def __init__(self, method):
self.method = method
def __get__(self, obj, T):
def transaction(*args, **kwargs):
state = Memento(obj)
try:
return self.method(obj, *args, **kwargs)
except:
state()
raise
return transaction

if __name__ == '__main__':
class NumObj(object):
def __init__(self, value):
self.value = value
def __repr__(self):
return '<%s: %r>' % (self.__class__.__name__, self.value)
def Increment(self):
self.value += 1
@transactional
def DoStuff(self):
self.value = '1111' # <- invalid value
self.Increment() # <- will fail and rollback

print
n = NumObj(-1)
print n
t = Transaction(n)
try:
for i in range(3):
n.Increment()
print n
t.Commit()
print '-- commited'
for i in range(3):
n.Increment()
print n
n.value += 'x' # will fail
print n
except:
t.Rollback()
print '-- rolled back'
print n
print '-- now doing stuff ...'
try:
n.DoStuff()
except:
print '-> doing stuff failed!'
import traceback
traceback.print_exc(0)
pass
print n
Loading

0 comments on commit 986b8c8

Please sign in to comment.