From bde115ccfd1e715d64b7ba727c55f3a56e52df4c Mon Sep 17 00:00:00 2001 From: Gennadiy Zlobin Date: Mon, 25 Jul 2011 15:47:09 +0700 Subject: [PATCH] Added new implementations. --- abstrfactory4.py | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ closure.py | 15 ++++++++++++ decorator4.py | 31 ++++++++++++++++++++++++ decorators.py | 18 ++++++++++++++ factory4.py | 35 +++++++++++++++++++++++++++ factorymethod.py | 15 ++++++++++++ flyweight.py | 51 ++++++++++++++++++++++++++++++++++++++++ iterator4.py | 21 +++++++++++++++++ observer3.py | 18 ++++++++++++++ state4.py | 56 ++++++++++++++++++++++++++++++++++++++++++++ strategy3.py | 13 +++++++++++ testing4.py | 47 +++++++++++++++++++++++++++++++++++++ 12 files changed, 381 insertions(+) create mode 100644 abstrfactory4.py create mode 100644 closure.py create mode 100644 decorator4.py create mode 100644 decorators.py create mode 100644 factory4.py create mode 100644 factorymethod.py create mode 100644 flyweight.py create mode 100644 iterator4.py create mode 100644 observer3.py create mode 100644 state4.py create mode 100644 strategy3.py create mode 100644 testing4.py diff --git a/abstrfactory4.py b/abstrfactory4.py new file mode 100644 index 0000000..0f40eb1 --- /dev/null +++ b/abstrfactory4.py @@ -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 diff --git a/closure.py b/closure.py new file mode 100644 index 0000000..bf34f48 --- /dev/null +++ b/closure.py @@ -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) +""" diff --git a/decorator4.py b/decorator4.py new file mode 100644 index 0000000..c692ffb --- /dev/null +++ b/decorator4.py @@ -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 diff --git a/decorators.py b/decorators.py new file mode 100644 index 0000000..e5b01b7 --- /dev/null +++ b/decorators.py @@ -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) diff --git a/factory4.py b/factory4.py new file mode 100644 index 0000000..8eec1f5 --- /dev/null +++ b/factory4.py @@ -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) diff --git a/factorymethod.py b/factorymethod.py new file mode 100644 index 0000000..354bcde --- /dev/null +++ b/factorymethod.py @@ -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 + diff --git a/flyweight.py b/flyweight.py new file mode 100644 index 0000000..981718d --- /dev/null +++ b/flyweight.py @@ -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() diff --git a/iterator4.py b/iterator4.py new file mode 100644 index 0000000..be69fc3 --- /dev/null +++ b/iterator4.py @@ -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, diff --git a/observer3.py b/observer3.py new file mode 100644 index 0000000..f54e0fa --- /dev/null +++ b/observer3.py @@ -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) diff --git a/state4.py b/state4.py new file mode 100644 index 0000000..7e3a9f0 --- /dev/null +++ b/state4.py @@ -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() diff --git a/strategy3.py b/strategy3.py new file mode 100644 index 0000000..f846f20 --- /dev/null +++ b/strategy3.py @@ -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() + diff --git a/testing4.py b/testing4.py new file mode 100644 index 0000000..89ffb4a --- /dev/null +++ b/testing4.py @@ -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()