Python设计模式(4):行为型

时间:2018-07-12 18:58:44   收藏:0   阅读:188

承接Python设计模式(3):结构型

13. Interpreter(解释器)

技术分享图片

意图:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Interpreter
‘‘‘

class Context:
    def __init__(self):
        self.input=""
        self.output=""

class AbstractExpression:
    def Interpret(self,context):
        pass

class Expression(AbstractExpression):
    def Interpret(self,context):
        print "terminal interpret"

class NonterminalExpression(AbstractExpression):
    def Interpret(self,context):
        print "Nonterminal interpret"

if __name__ == "__main__":
    context= ""
    c = []
    c = c + [Expression()]
    c = c + [NonterminalExpression()]
    c = c + [Expression()]
    c = c + [Expression()]
    for a in c:
        a.Interpret(context)

14. Template Method(模板方法)

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Template Method
‘‘‘

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

15. Chain of Responsibility(责任链)

技术分享图片

意图:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

适用性:

#!/usr/bin/python
#coding:utf8

"""
Chain
"""
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()

16. Command(命令)

技术分享图片

意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

适用性:

#!/usr/bin/python
#coding:utf8

"""
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()

17. Iterator(迭代器)

技术分享图片

意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Interator
‘‘‘
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

print " "

print(‘Counting to five...‘)
for number in count_to_five():
    print number

print " "

18. Mediator(中介者)

技术分享图片

意图:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
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()

19. Memento(备忘录)

技术分享图片

意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Memento
‘‘‘

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)

20. Observer(观察者)

技术分享图片

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Observer
‘‘‘


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

21. State(状态)

技术分享图片

意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
State
‘‘‘

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

22. Strategy(策略)

技术分享图片

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

适用性:

#!/usr/bin/python
#coding:utf8
"""
Strategy
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()

23. Visitor(访问者)

技术分享图片

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Visitor
‘‘‘
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)

参考文章

https://www.cnblogs.com/Liqiongyu/p/5916710.html

承接Python设计模式(3):结构型

13. Interpreter(解释器)

技术分享图片

意图:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Interpreter
‘‘‘

class Context:
    def __init__(self):
        self.input=""
        self.output=""

class AbstractExpression:
    def Interpret(self,context):
        pass

class Expression(AbstractExpression):
    def Interpret(self,context):
        print "terminal interpret"

class NonterminalExpression(AbstractExpression):
    def Interpret(self,context):
        print "Nonterminal interpret"

if __name__ == "__main__":
    context= ""
    c = []
    c = c + [Expression()]
    c = c + [NonterminalExpression()]
    c = c + [Expression()]
    c = c + [Expression()]
    for a in c:
        a.Interpret(context)

14. Template Method(模板方法)

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Template Method
‘‘‘

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

15. Chain of Responsibility(责任链)

技术分享图片

意图:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

适用性:

#!/usr/bin/python
#coding:utf8

"""
Chain
"""
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()

16. Command(命令)

技术分享图片

意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。

适用性:

#!/usr/bin/python
#coding:utf8

"""
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()

17. Iterator(迭代器)

技术分享图片

意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Interator
‘‘‘
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

print " "

print(‘Counting to five...‘)
for number in count_to_five():
    print number

print " "

18. Mediator(中介者)

技术分享图片

意图:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
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()

19. Memento(备忘录)

技术分享图片

意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Memento
‘‘‘

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)

20. Observer(观察者)

技术分享图片

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Observer
‘‘‘


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

21. State(状态)

技术分享图片

意图:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
State
‘‘‘

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

22. Strategy(策略)

技术分享图片

意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

适用性:

#!/usr/bin/python
#coding:utf8
"""
Strategy
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()

23. Visitor(访问者)

技术分享图片

意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

适用性:

#!/usr/bin/python
#coding:utf8
‘‘‘
Visitor
‘‘‘
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)

参考文章

https://www.cnblogs.com/Liqiongyu/p/5916710.html

原文:https://www.cnblogs.com/mac1993/p/9300924.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!