" name="sm-site-verification"/>
侧边栏壁纸
博主头像
PySuper 博主等级

千里之行,始于足下

  • 累计撰写 206 篇文章
  • 累计创建 14 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

23种设计模式及Python实现 -- 行为型(一)

PySuper
2019-10-21 / 0 评论 / 0 点赞 / 22 阅读 / 0 字
温馨提示:
本文最后更新于2024-05-28,若内容或图片失效,请留言反馈。 所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

解释器

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

  • 当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式
  • 该文法简单对于复杂的文法, 文法的类层次变得庞大而无法管理
  • 效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式(如:正则表达式通常被转换成状态机)
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)

模板方法

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

  • 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复
  • 控制子类扩展:模板方法只在特定点调用“hook ”操作(参见效果一节),这样就只允许在这些点进行扩展
ingredients = "spam eggs apple"
line = '-' * 10

def iter_elements(getter, action):
    for element in getter():        
        action(element)    
        print(line)

def rev_elements(getter, action):
    for element in getter()[::-1]:        
        action(element)    
        print(line) 

def get_list():    
    return ingredients.split() 
 
def get_lists():
    return [list(x) for x in ingredients.split()]

def print_item(item):    
    print(item) 

def reverse_item(item):
    print(item[::-1]) 

def make_template(skeleton, getter, action):
    def template():        
        skeleton(getter, action)    
    return template 


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

for template in templates:    
    template()

责任链

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

  • 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定
  • 你想在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
  • 可处理一个请求的对象集合应被动态指定
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()

命令

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

  • 抽象出待执行的动作以参数化某对象,你可用过程语言中的回调函数表达这种参数化机制
  • 在不同的时刻指定、排列和执行请求
  • 支持取消操作
  • 支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍
  • 用构建在原语操作上的高层操作构造一个系统
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 = []

    command_stack.append(MoveFileCommand('foo.txt', 'bar.txt'))
    command_stack.append(MoveFileCommand('bar.txt', 'baz.txt'))

    for cmd in command_stack:
        cmd.execute()

    for cmd in reversed(command_stack):
        cmd.undo()

迭代器

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

  • 访问一个聚合对象的内容而无需暴露它的内部表示
  • 持对聚合对象的多种遍历
  • 为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)
def count_to(count):
    numbers = ["one", "two", "three", "four", "five"]
    for pos, number in zip(range(count), numbers):
        yield number

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 " "
0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区