Python设计模式

这两天在PythonTip刷题,突然看到这里提供了Python的设计模式demo,正是我多年来想找的东西。

PythonTip
Python设计模式_第1张图片
Python设计模式

于是乎,我就动用了我的爬爬爬爬爬虫把这些代码都爬下来了,放到,有时间就过来看看。25种设计模式,还是挺多的。

borg

class Borg:
    __shared_state = {}

    def __init__(self):
        self.__dict__ = self.__shared_state

    def __str__(self):
        return self.state


class YourBorg(Borg):
    pass

if __name__ == '__main__':
    rm1 = Borg()
    rm2 = Borg()

    rm1.state = 'Idle'
    rm2.state = 'Running'

    print('rm1:', rm1)
    print('rm2:', rm2)

    rm2.state = 'Zombie'

    print('rm1:', rm1)
    print('rm2:', rm2)

    print('rm1 id:', id(rm1))
    print('rm2 id:', id(rm2))

    rm3 = YourBorg()

    print('rm1:', rm1)
    print('rm2:', rm2)
    print('rm3:', rm3)


facade

"""http://dpip.testingperspective.com/?p=26"""

import time

SLEEP = 0.5


# Complex Parts
class TC1:
    def run(self):
        print("###### In Test 1 ######")
        time.sleep(SLEEP)
        print("Setting up")
        time.sleep(SLEEP)
        print("Running test")
        time.sleep(SLEEP)
        print("Tearing down")
        time.sleep(SLEEP)
        print("Test Finished\n")


class TC2:
    def run(self):
        print("###### In Test 2 ######")
        time.sleep(SLEEP)
        print("Setting up")
        time.sleep(SLEEP)
        print("Running test")
        time.sleep(SLEEP)
        print("Tearing down")
        time.sleep(SLEEP)
        print("Test Finished\n")


class TC3:
    def run(self):
        print("###### In Test 3 ######")
        time.sleep(SLEEP)
        print("Setting up")
        time.sleep(SLEEP)
        print("Running test")
        time.sleep(SLEEP)
        print("Tearing down")
        time.sleep(SLEEP)
        print("Test Finished\n")


# Facade
class TestRunner:
    def __init__(self):
        self.tc1 = TC1()
        self.tc2 = TC2()
        self.tc3 = TC3()
        self.tests = [i for i in (self.tc1, self.tc2, self.tc3)]

    def runAll(self):
        [i.run() for i in self.tests]


# Client
if __name__ == '__main__':
    testrunner = TestRunner()
    testrunner.runAll()


chain

# http://www.testingperspective.com/wiki/doku.php/collaboration/chetan/designpatternsinpython/chain-of-responsibilitypattern


class Handler:
    def successor(self, successor):
        self.successor = successor


class ConcreteHandler1(Handler):
    def handle(self, request):
        if request > 0 and request <= 10:
            print("in handler1")
        else:
            self.successor.handle(request)
 

class ConcreteHandler2(Handler):
    def handle(self, request):
        if request > 10 and request <= 20:
            print("in handler2")
        else:
            self.successor.handle(request)
 

class ConcreteHandler3(Handler):
    def handle(self, request):
        if request > 20 and request <= 30:
            print("in handler3")
        else:
            print('end of chain, no handler for {}'.format(request))
 

class Client:
    def __init__(self):
        h1 = ConcreteHandler1()
        h2 = ConcreteHandler2()
        h3 = ConcreteHandler3()

        h1.successor(h2)
        h2.successor(h3)

        requests = [2, 5, 14, 22, 18, 3, 35, 27, 20]
        for request in requests:
            h1.handle(request)


if __name__ == "__main__":
    client = Client()


abstract_factory

# http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/

"""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
if __name__ == "__main__":
    shop = PetShop()
    for i in range(3):
        shop.pet_factory = get_factory()
        shop.show_pet()
        print("=" * 20)


bridge

# http://en.wikibooks.org/wiki/Computer_Science_Design_Patterns/Bridge_Pattern#Python


# ConcreteImplementor 1/2
class DrawingAPI1(object):
    def draw_circle(self, x, y, radius):
        print('API1.circle at {}:{} radius {}'.format(x, y, radius))


# ConcreteImplementor 2/2
class DrawingAPI2(object):
    def draw_circle(self, x, y, radius):
        print('API2.circle at {}:{} radius {}'.format(x, y, radius))


# Refined Abstraction
class CircleShape(object):
    def __init__(self, x, y, radius, drawing_api):
        self._x = x
        self._y = y
        self._radius = radius
        self._drawing_api = drawing_api
 
    # low-level i.e. Implementation specific
    def draw(self):
        self._drawing_api.draw_circle(self._x, self._y, self._radius)
 
    # high-level i.e. Abstraction specific
    def scale(self, pct):
        self._radius *= pct


def main():
    shapes = (
        CircleShape(1, 2, 3, DrawingAPI1()),
        CircleShape(5, 7, 11, DrawingAPI2())
    )
 
    for shape in shapes:
        shape.scale(2.5)
        shape.draw()
 

if __name__ == '__main__':
    main()


memento

"""code.activestate.com/recipes/413838-memento-closure/"""

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 really 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 st in self.states:
            st()


class transactional(object):
    """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


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


if __name__ == '__main__':
    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)


mediator

"""http://dpip.testingperspective.com/?p=28"""

import time 


class TC:
    def __init__(self):                         
        self._tm = tm                         
        self._bProblem = 0             

    def setup(self):                         
        print("Setting up the Test")                         
        time.sleep(1)                         
        self._tm.prepareReporting()   

    def execute(self):                         
        if not self._bProblem:                                      
            print("Executing the test")                                      
            time.sleep(1)                         
        else:                                      
            print("Problem in setup. Test not executed.")             

    def tearDown(self):                         
        if not self._bProblem:                                      
            print("Tearing down")                                      
            time.sleep(1)                                      
            self._tm.publishReport()                         
        else:                                      
            print("Test not executed. No tear down required.")             

    def setTM(self, TM):
        self._tm = tm             

    def setProblem(self, value):                         
        self._bProblem = value 


class Reporter:
    def __init__(self):                         
        self._tm = None             

    def prepare(self):                         
        print("Reporter Class is preparing to report the results")                         
        time.sleep(1)             

    def report(self):                         
        print("Reporting the results of Test")                         
        time.sleep(1)             

    def setTM(self, TM):
        self._tm = tm 


class DB:
    def __init__(self):                         
        self._tm = None             

    def insert(self):                         
        print("Inserting the execution begin status in the Database")                         
        time.sleep(1)                         
        #Following code is to simulate a communication from DB to TC                         
        import random                         
        if random.randrange(1, 4) == 3:
            return -1             

    def update(self):                         
        print("Updating the test results in Database")                         
        time.sleep(1)             

    def setTM(self, TM):
        self._tm = tm 


class TestManager:
    def __init__(self):                         
        self._reporter = None                         
        self._db = None                         
        self._tc = None             

    def prepareReporting(self):                         
        rvalue = self._db.insert()                         
        if rvalue == -1:                                      
            self._tc.setProblem(1)                                      
            self._reporter.prepare()             

    def setReporter(self, reporter):                         
        self._reporter = reporter             

    def setDB(self, db):                         
        self._db = db             

    def publishReport(self):                         
        self._db.update()                         
        rvalue = self._reporter.report()             

    def setTC(self, tc):
        self._tc = tc 


if __name__ == '__main__':             
    reporter = Reporter()             
    db = DB()             
    tm = TestManager()             
    tm.setReporter(reporter)             
    tm.setDB(db)             
    reporter.setTM(tm)             
    db.setTM(tm)             
    # For simplification we are looping on the same test.             
    # Practically, it could be about various unique test classes and their
    # objects
    while (True):                         
        tc = TC()                         
        tc.setTM(tm)                         
        tm.setTC(tc)                         
        tc.setup()                         
        tc.execute()                         
        tc.tearDown()


prototype

import copy


class Prototype:
    def __init__(self):
        self._objects = {}

    def register_object(self, name, obj):
        """Register an object"""
        self._objects[name] = obj

    def unregister_object(self, name):
        """Unregister an object"""
        del self._objects[name]

    def clone(self, name, **attr):
        """Clone a registered object and update inner attributes dictionary"""
        obj = copy.deepcopy(self._objects.get(name))
        obj.__dict__.update(attr)
        return obj


def main():
    class A:
        pass

    a = A()
    prototype = Prototype()
    prototype.register_object('a', a)
    b = prototype.clone('a', a=1, b=2, c=3)

    print(a)
    print(b.a, b.b, b.c)


if __name__ == '__main__':
    main()


decorator

# http://stackoverflow.com/questions/3118929/implementing-the-decorator-pattern-in-python


class foo(object):
    def f1(self):
        print("original f1")

    def f2(self):
        print("original f2")


class foo_decorator(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)

u = foo()
v = foo_decorator(u)
v.f1()
v.f2()


adapter

# http://ginstrom.com/scribbles/2008/11/06/generic-adapter-class-in-python/

import os


class Dog(object):
    def __init__(self):
        self.name = "Dog"

    def bark(self):
        return "woof!"


class Cat(object):
    def __init__(self):
        self.name = "Cat"

    def meow(self):
        return "meow!"


class Human(object):
    def __init__(self):
        self.name = "Human"

    def speak(self):
        return "'hello'"


class Car(object):
    def __init__(self):
        self.name = "Car"

    def make_noise(self, octane_level):
        return "vroom%s" % ("!" * octane_level)


class Adapter(object):
    """
    Adapts an object by replacing methods.
    Usage:
    dog = Dog
    dog = Adapter(dog, dict(make_noise=dog.bark))
    """
    def __init__(self, obj, adapted_methods):
        """We set the adapted methods in the object's dict"""
        self.obj = obj
        self.__dict__.update(adapted_methods)

    def __getattr__(self, attr):
        """All non-adapted calls are passed to the object"""
        return getattr(self.obj, attr)


def main():
    objects = []
    dog = Dog()
    objects.append(Adapter(dog, dict(make_noise=dog.bark)))
    cat = Cat()
    objects.append(Adapter(cat, dict(make_noise=cat.meow)))
    human = Human()
    objects.append(Adapter(human, dict(make_noise=human.speak)))
    car = Car()
    car_noise = lambda: car.make_noise(3)
    objects.append(Adapter(car, dict(make_noise=car_noise)))

    for obj in objects:
        print("A", obj.name, "goes", obj.make_noise())


if __name__ == "__main__":
    main()


factory_method

#encoding=utf-8
"""http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/"""


class GreekGetter:
    """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 self.trans[msgid]
        except KeyError:
            return str(msgid)


class EnglishGetter:
    """Simply echoes the msg ids"""     
    def get(self, msgid):
        return str(msgid)


def get_localizer(language="English"):
    """The factory method"""
    languages = dict(English=EnglishGetter, Greek=GreekGetter)
    return languages[language]()

# Create our localizers
e, g = get_localizer("English"), get_localizer("Greek")
# Localize some text
for msgid in "dog parrot cat bear".split():
    print(e.get(msgid), g.get(msgid))


observer

"""http://code.activestate.com/recipes/131499-observer-pattern/"""


class Subject(object):
    def __init__(self):
        self._observers = []

    def attach(self, observer):
        if not observer in self._observers:
            self._observers.append(observer)

    def detach(self, observer):
        try:
            self._observers.remove(observer)
        except ValueError:
            pass

    def notify(self, modifier=None):
        for observer in self._observers:
            if modifier != observer:
                observer.update(self)


# Example usage
class Data(Subject):
    def __init__(self, name=''):
        Subject.__init__(self)
        self.name = name
        self._data = 0

    @property
    def data(self):
        return self._data
    
    @data.setter
    def data(self, value):
        self._data = value
        self.notify()


class HexViewer:
    def update(self, subject):
        print('HexViewer: Subject %s has data 0x%x' %
              (subject.name, subject.data))


class DecimalViewer:
    def update(self, subject):
        print('DecimalViewer: Subject %s has data %d' %
              (subject.name, subject.data))


# Example usage...
def main():
    data1 = Data('Data 1')
    data2 = Data('Data 2')
    view1 = DecimalViewer()
    view2 = HexViewer()
    data1.attach(view1)
    data1.attach(view2)
    data2.attach(view2)
    data2.attach(view1)

    print("Setting Data 1 = 10")
    data1.data = 10
    print("Setting Data 2 = 15")
    data2.data = 15
    print("Setting Data 1 = 3")
    data1.data = 3
    print("Setting Data 2 = 5")
    data2.data = 5
    print("Detach HexViewer from data1 and data2.")
    data1.detach(view2)
    data2.detach(view2)
    print("Setting Data 1 = 10")
    data1.data = 10
    print("Setting Data 2 = 15")
    data2.data = 15


if __name__ == '__main__':
    main()


command

import os


class MoveFileCommand(object):
    def __init__(self, src, dest):
        self.src = src
        self.dest = dest

    def execute(self):
        self()
        
    def __call__(self):
        print('renaming {} to {}'.format(self.src, self.dest))
        os.rename(self.src, self.dest)

    def undo(self):
        print('renaming {} to {}'.format(self.dest, self.src))
        os.rename(self.dest, self.src)


if __name__ == "__main__":
    command_stack = []

    # commands are just pushed into the command stack
    command_stack.append(MoveFileCommand('foo.txt', 'bar.txt'))
    command_stack.append(MoveFileCommand('bar.txt', 'baz.txt'))


    # they can be executed later on
    for cmd in command_stack:
        cmd.execute()

    # and can also be undone at will
    for cmd in reversed(command_stack):
        cmd.undo()


iterator

"""http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/"""

"""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"]
    # enumerate() returns a tuple containing a count (from start which
    # defaults to 0) and the values obtained from iterating over sequence
    for pos, number in zip(range(count), numbers):
        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, end=' ')

print()

print('Counting to five...')
for number in count_to_five():
    print(number, end=' ')

print()


template

"""http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/"""

"""An example of the Template pattern in Python"""  

ingredients = "spam eggs apple"
line = '-' * 10


# Skeletons
def iter_elements(getter, action):     
    """Template skeleton that iterates items"""      
    for element in getter():         
        action(element)     
        print(line)  


def rev_elements(getter, action):
    """Template skeleton that iterates items in reverse order"""      
    for element in getter()[::-1]:         
        action(element)     
        print(line)  


# Getters
def get_list():     
    return ingredients.split()  


def get_lists():
    return [list(x) for x in ingredients.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()


null

#!/user/bin/env python 

"""http://code.activestate.com/recipes/68205-null-object-design-pattern/"""


class Null:
    def __init__(self, *args, **kwargs):
        """Ignore parameters."""
        return None

    def __call__(self, *args, **kwargs):
        """Ignore method calls."""
        return self

    def __getattr__(self, mname):
        """Ignore attribute requests."""
        return self

    def __setattr__(self, name, value):
        """Ignore attribute setting."""
        return self

    def __delattr__(self, name):
        """Ignore deleting attributes."""
        return self

    def __repr__(self):
        """Return a string representation."""
        return ""

    def __str__(self):
        """Convert to a string and return it."""
        return "Null"


def test():
    """Perform some decent tests, or rather: demos."""

    # constructing and calling

    n = Null()
    print(n)

    n = Null('value')
    print(n)

    n = Null('value', param='value')
    print(n)

    n()
    n('value')
    n('value', param='value')
    print(n)

    # attribute handling

    n.attr1
    print('attr1', n.attr1)
    n.attr1.attr2
    n.method1()
    n.method1().method2()
    n.method('value')
    n.method(param='value')
    n.method('value', param='value')
    n.attr1.method1()
    n.method1().attr1

    n.attr1 = 'value'
    n.attr1.attr2 = 'value'

    del n.attr1
    del n.attr1.attr2.attr3

    # representation and conversion to a string
    
    assert repr(n) == ''
    assert str(n) == 'Null'


if __name__ == '__main__':
    test()


state

"""Implementation of the state pattern"""  

'''http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/'''


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
if __name__ == '__main__':
    radio = Radio() 
    actions = [radio.scan] * 2 + [radio.toggle_amfm] + [radio.scan] * 2 
    actions = actions * 2 

    for action in actions:     
        action()


builder

#!/usr/bin/python
# -*- coding : utf-8 -*-

"""
    @author: Diogenes Augusto Fernandes Herminio 
    https://gist.github.com/420905#file_builder_python.py
"""


# Director
class Director(object):
    def __init__(self):
        self.builder = None

    def construct_building(self):
        self.builder.new_building()
        self.builder.build_floor()
        self.builder.build_size()

    def get_building(self):
        return self.builder.building


# Abstract Builder
class Builder(object):
    def __init__(self):
        self.building = None

    def new_building(self):
        self.building = Building()


# Concrete Builder
class BuilderHouse(Builder):
    def build_floor(self):
        self.building.floor = 'One'

    def build_size(self):
        self.building.size = 'Big'


class BuilderFlat(Builder):
    def build_floor(self):
        self.building.floor = 'More than One'
        
    def build_size(self):
        self.building.size = 'Small'


# Product
class Building(object):
    def __init__(self):
        self.floor = None
        self.size = None

    def __repr__(self):
        return 'Floor: %s | Size: %s' % (self.floor, self.size)


# Client
if __name__ == "__main__":
    director = Director()
    director.builder = BuilderHouse()
    director.construct_building()
    building = director.get_building()
    print(building)
    director.builder = BuilderFlat()
    director.construct_building()
    building = director.get_building()
    print(building)


graph_search

class GraphSearch:
    """Graph search emulation in python, from source
    http://www.python.org/doc/essays/graphs/"""

    def __init__(self, graph):
        self.graph = graph 
    
    def find_path(self, start, end, path=[]):
        self.start = start
        self.end = end
        self.path = path

        self.path += [self.start]
        if self.start == self.end:
            return self.path
        if not self.graph.has_key(self.start):
            return None
        for node in self.graph[self.start]:
            if node not in self.path:
                newpath = self.find_path(node, self.end, self.path)
                if newpath:
                    return newpath
        return None

    def find_all_path(self, start, end, path=[]):            
        self.start = start
        self.end = end
        self.path = path
        self.path += [self.start]
        if self.start == self.end:
            return [self.path]
        if not self.graph.has_key(self.start):
            return []
        paths = []
        for node in self.graph[self.start]:
            if node not in self.path:
                newpaths = self.find_all_path(node, self.end, self.path)
                for newpath in newpaths:
                    paths.append(newpath)                
        return paths

    def find_shortest_path(self, start, end, path=[]):         
        self.start = start
        self.end = end
        self.path = path
        
        self.path += [self.start]
        if self.start == self.end:
            return self.path
        if not self.graph.has_key(self.start):
            return None
        shortest = None
        for node in self.graph[self.start]:
            if node not in self.path:
                newpath = self.find_shortest_path(node, self.end, self.path)
                if newpath:
                    if not shortest or len(newpath) < len(shortest):
                        shortest = newpath
        return shortest

#example of graph usage
graph = {'A': ['B', 'C'],
         'B': ['C', 'D'],
         'C': ['D'],
         'D': ['C'],
         'E': ['F'],
         'F': ['C']   
         }

#inistialization of new graph search object
graph1 = GraphSearch(graph)


print graph1.find_path('A', 'D')
print graph1.find_all_path('A', 'D')
print graph1.find_shortest_path('A', 'D')


flyweight

"""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 = object.__new__(cls)             
            Card._CardPool[value + suit] = obj             
            obj.value, obj.suit = value, suit          
        return obj

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

    def __repr__(self):         
        return "" % (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))


pool

"""http://stackoverflow.com/questions/1514120/python-implementation-of-the-object-pool-design-pattern"""


class QueueObject():
    def __init__(self, queue, auto_get=False):
        self._queue = queue
        self.object = self._queue.get() if auto_get else None

    def __enter__(self):
        if self.object is None:
            self.object = self._queue.get()
        return self.object

    def __exit__(self, type, value, traceback):
        if self.object is not None:
            self._queue.put(self.object)
            self.object = None

    def __del__(self):
        if self.object is not None:
            self._queue.put(self.object)
            self.object = None


def main():
    try:
        import queue
    except ImportError:  # python 2.x compatibility
        import Queue as queue

    def test_object(queue):
        queue_object = QueueObject(queue, True)
        print('Inside func: {}'.format(queue_object.object))

    sample_queue = queue.Queue()

    sample_queue.put('yam')
    with QueueObject(sample_queue) as obj:
        print('Inside with: {}'.format(obj))
    print('Outside with: {}'.format(sample_queue.get()))

    sample_queue.put('sam')
    test_object(sample_queue)
    print('Outside func: {}'.format(sample_queue.get()))

    if not sample_queue.empty():
        print(sample_queue.get())


if __name__ == '__main__':
    main()


composite

"""
A class which defines a composite object which can store
hieararchical dictionaries with names.

This class is same as a hiearchical dictionary, but it
provides methods to add/access/modify children by name, 
like a Composite.

Created Anand B Pillai     

"""
__author__ = "Anand B Pillai"
__maintainer__ = "Anand B Pillai"
__version__ = "0.2"


def normalize(val):
    """ Normalize a string so that it can be used as an attribute
    to a Python object """
    
    if val.find('-') != -1:
        val = val.replace('-', '_')

    return val


def denormalize(val):
    """ De-normalize a string """

    if val.find('_') != -1:
        val = val.replace('_', '-')

    return val


class SpecialDict(dict):
    """ A dictionary type which allows direct attribute
    access to its keys """

    def __getattr__(self, name):

        if name in self.__dict__:
            return self.__dict__[name]
        elif name in self:
            return self.get(name)
        else:
            # Check for denormalized name
            name = denormalize(name)
            if name in self:
                return self.get(name)
            else:
                raise AttributeError('no attribute named %s' % name)

    def __setattr__(self, name, value):

        if name in self.__dict__:
            self.__dict__[name] = value
        elif name in self:
            self[name] = value
        else:
            # Check for denormalized name
            name2 = denormalize(name)
            if name2 in self:
                self[name2] = value
            else:
                # New attribute
                self[name] = value
        

class CompositeDict(SpecialDict):
    """ A class which works like a hierarchical dictionary.
    This class is based on the Composite design-pattern """

    ID = 0

    def __init__(self, name=''):

        if name:
            self._name = name
        else:
            self._name = ''.join(('id#', str(self.__class__.ID)))
            self.__class__.ID += 1

        self._children = []
        # Link  back to father
        self._father = None
        self[self._name] = SpecialDict()

    def __getattr__(self, name):

        if name in self.__dict__:
            return self.__dict__[name]
        elif name in self:
            return self.get(name)
        else:
            # Check for denormalized name
            name = denormalize(name)
            if name in self:
                return self.get(name)
            else:
                # Look in children list
                child = self.findChild(name)
                if child:
                    return child
                else:
                    attr = getattr(self[self._name], name)
                    if attr:
                        return attr
                    
                    raise AttributeError('no attribute named %s' % name)

    def isRoot(self):
        """ Return whether I am a root component or not """

        # If I don't have a parent, I am root
        return not self._father
    
    def isLeaf(self):
        """ Return whether I am a leaf component or not """

        # I am a leaf if I have no children
        return not self._children

    def getName(self):
        """ Return the name of this ConfigInfo object """

        return self._name

    def getIndex(self, child):
        """ Return the index of the child ConfigInfo object 'child' """
        
        if child in self._children:
            return self._children.index(child)
        else:
            return -1

    def getDict(self):
        """ Return the contained dictionary """
        
        return self[self._name]

    def getProperty(self, child, key):
        """ Return the value for the property for child
        'child' with key 'key' """

        # First get the child's dictionary
        childDict = self.getInfoDict(child)
        if childDict:
            return childDict.get(key, None)

    def setProperty(self, child, key, value):
        """ Set the value for the property 'key' for
        the child 'child' to 'value' """

        # First get the child's dictionary
        childDict = self.getInfoDict(child)
        if childDict:
            childDict[key] = value
    
    def getChildren(self):
        """ Return the list of immediate children of this object """
        
        return self._children

    def getAllChildren(self):
        """ Return the list of all children of this object """
        
        l = []
        for child in self._children:
            l.append(child)
            l.extend(child.getAllChildren())
            
        return l

    def getChild(self, name):
        """ Return the immediate child object with the given name """
        
        for child in self._children:
            if child.getName() == name:
                return child

    def findChild(self, name):
        """ Return the child with the given name from the tree """

        # Note - this returns the first child of the given name
        # any other children with similar names down the tree
        # is not considered.
        
        for child in self.getAllChildren():
            if child.getName() == name:
                return child

    def findChildren(self, name):
        """ Return a list of children with the given name from the tree """

        # Note: this returns a list of all the children of a given
        # name, irrespective of the depth of look-up.
        
        children = []
        
        for child in self.getAllChildren():
            if child.getName() == name:
                children.append(child)

        return children
            
    def getPropertyDict(self):
        """ Return the property dictionary """
        
        d = self.getChild('__properties')
        if d:
            return d.getDict()
        else:
            return {}
        
    def getParent(self):
        """ Return the person who created me """

        return self._father
    
    def __setChildDict(self, child):
        """ Private method to set the dictionary of the child
        object 'child' in the internal dictionary """
        
        d = self[self._name]
        d[child.getName()] = child.getDict()

    def setParent(self, father):
        """ Set the parent object of myself """

        # This should be ideally called only once
        # by the father when creating the child :-)
        # though it is possible to change parenthood
        # when a new child is adopted in the place
        # of an existing one - in that case the existing
        # child is orphaned - see addChild and addChild2
        # methods !
        self._father = father
        
    def setName(self, name):
        """ Set the name of this ConfigInfo object to 'name' """        

        self._name = name

    def setDict(self, d):
        """ Set the contained dictionary """
        
        self[self._name] = d.copy()
        
    def setAttribute(self, name, value):
        """ Set a name value pair in the contained dictionary """
        
        self[self._name][name] = value

    def getAttribute(self, name):
        """ Return value of an attribute from the contained dictionary """
        
        return self[self._name][name]

    def addChild(self, name, force=False):
        """ Add a new child 'child' with the name 'name'.
        If the optional flag 'force' is set to True, the
        child object is overwritten if it is already there.

        This function returns the child object, whether
        new or existing """
        
        if type(name) != str:
            raise ValueError('Argument should be a string!')
        
        child = self.getChild(name)
        if child:
            # print 'Child %s present!' % name
            # Replace it if force==True
            if force:
                index = self.getIndex(child)
                if index != -1:
                    child = self.__class__(name)
                    self._children[index] = child
                    child.setParent(self)
                    
                    self.__setChildDict(child)
            return child
        else:
            child = self.__class__(name)
            child.setParent(self)
            
            self._children.append(child)
            self.__setChildDict(child)

            return child
        
    def addChild2(self, child):
        """ Add the child object 'child'. If it is already present,
        it is overwritten by default """
        
        currChild = self.getChild(child.getName())
        if currChild:
            index = self.getIndex(currChild)
            if index != -1:
                self._children[index] = child
                child.setParent(self)
                # Unset the existing child's parent
                currChild.setParent(None)
                del currChild
                
                self.__setChildDict(child)
        else:
            child.setParent(self)            
            self._children.append(child)
            self.__setChildDict(child)


if __name__ == "__main__":
    window = CompositeDict('Window')
    frame = window.addChild('Frame')
    tfield = frame.addChild('Text Field')
    tfield.setAttribute('size', '20')
    
    btn = frame.addChild('Button1')
    btn.setAttribute('label', 'Submit')

    btn = frame.addChild('Button2')
    btn.setAttribute('label', 'Browse')

    # print(window)
    # print(window.Frame)
    # print(window.Frame.Button1)
    # print(window.Frame.Button2)
    print(window.Frame.Button1.label)
    print(window.Frame.Button2.label)


strategy

"""http://stackoverflow.com/questions/963965/how-is-this-strategy-pattern-written-in-python-the-sample-in-wikipedia

In most of other languages Strategy pattern is implemented via creating some base strategy interface/abstract class and
subclassing it with a number of concrete strategies (as we can see at http://en.wikipedia.org/wiki/Strategy_pattern),
however Python supports higher-order functions and allows us to have only one class and inject functions into it's
instances, as shown in this example.
"""
import types


class StrategyExample:
    def __init__(self, func=None):
        self.name = 'Strategy Example 0'         
        if func is not None:
            self.execute = types.MethodType(func, self)      

    def execute(self):         
        print(self.name)   


def execute_replacement1(self):
    print(self.name + ' from execute 1')   


def execute_replacement2(self):
    print(self.name + ' from execute 2')  


if __name__ == '__main__':
    strat0 = StrategyExample()     

    strat1 = StrategyExample(execute_replacement1)
    strat1.name = 'Strategy Example 1'     

    strat2 = StrategyExample(execute_replacement2)
    strat2.name = 'Strategy Example 2'

    strat0.execute()
    strat1.execute()     
    strat2.execute()


proxy

import time 


class SalesManager:
    def work(self):                         
        print("Sales Manager working...")             

    def talk(self):                         
        print("Sales Manager ready to talk") 


class Proxy:
    def __init__(self):                         
        self.busy = 'No'                         
        self.sales = None             

    def work(self):
        print("Proxy checking for Sales Manager availability")                         
        if self.busy == 'No':                                      
            self.sales = SalesManager()                                      
            time.sleep(2)
            self.sales.talk()                         
        else:                                      
            time.sleep(2)
            print("Sales Manager is busy")


if __name__ == '__main__':
    p = Proxy()
    p.work()
    p.busy = 'Yes'
    p.work()


visitor

"""http://peter-hoffmann.com/2010/extrinsic-visitor-pattern-python-inheritance.html"""


class Node(object):
    pass


class A(Node):
    pass


class B(Node):
    pass


class C(A, B):
    pass


class Visitor(object):
    def visit(self, node, *args, **kwargs):
        meth = None
        for cls in node.__class__.__mro__:
            meth_name = 'visit_'+cls.__name__
            meth = getattr(self, meth_name, None)
            if meth:
                break

        if not meth:
            meth = self.generic_visit
        return meth(node, *args, **kwargs)

    def generic_visit(self, node, *args, **kwargs):
        print('generic_visit '+node.__class__.__name__)

    def visit_B(self, node, *args, **kwargs):
        print('visit_B '+node.__class__.__name__)


a = A()
b = B()
c = C()
visitor = Visitor()
visitor.visit(a)
visitor.visit(b)
visitor.visit(c)


顺序是乱的,因为爬虫是多线程的,反正内容都在这里。爬虫在我的Github里面,可以自己找。

最后还是强调一点,这些代码来自PythonTip,版权归PythonTip所有。

P.s 欢迎大家闲来无事一起刷题啊!

你可能感兴趣的:(Python设计模式)