【设计模式|下】行为型模式

every blog every motto: You can do more than you think.
https://blog.csdn.net/weixin_39190382?type=blog

0. 前言

  1. 【设计模式 | 上】【创建型】
  2. 【设计模式 | 中】【行为型】
  3. 【设计模式 | 下】【行为型】
    1. 观察者模式
    2. 状态模式
    3. 策略模式
    4. 职责链模式
    5. 命令模式
    6. 访问模式
    7. 调停者模式
    8. 备忘录模式
    9. 迭代器模式
    10. 解释器模式
    11. 模板方法模式

1. 正文

1.3 行为型

1.3.1 观察者模式–Observer

 
'''
Observer
'''
# 观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式
# 当我们希望一个对象的状态发生变化,那么依赖与它的所有对象都能相应变化(获得通知),那么就可以用到Observer模式, 其中的这些依赖对象就是观察者的对象,那个要发生变化的对象就是所谓’观察者’
 
class ObserverBase(object):
    '''观察者基类''' #放哨者
 
    def __init__(self):
        self._observerd_list = [] #被通知对象
 
    def attach(self,observe_subject):
        '''
        添加要观察的对象
        :param observe_subject:
        :return:
        '''
        if observe_subject not in self._observerd_list:
            self._observerd_list.append(observe_subject)
            print("[%s]已经将[%s]加入观察队列..."%(self.name,observe_subject) )
    def detach(self,observe_subject):
        '''
        解除观察关系
        :param observe_subject:
        :return:
        '''
        try:
            self._observerd_list.remove(observe_subject)
            print("不再观察[%s]" %observe_subject)
        except ValueError:
            pass
 
    def notify(self):
        '''
        通知所有被观察者
        :return:
        '''
        for objserver in self._observerd_list:
            objserver.update(self)
 
 
class Observer(ObserverBase):
    '''观察者类'''
 
    def __init__(self,name):
        super(Observer,self).__init__()
        self.name = name
        self._msg = ''
 
    @property  #外部执行d.eat 去掉括号
    def msg(self):
        '''
        当前状况
        :return:
        '''
        return self._msg
 
    @msg.setter  #设置属性(一个方法变成一个静态的属性)
    def msg(self,content):
        self._msg = content
        self.notify()
#目前结论:一个方法变成一个静态的属性 (装饰了@property)
#通过另外一个相同名字的方法(装饰@msg.setter )进行修改该属性
#简单: d = Observer('xxx')
       #print(d.msg)  结果:空
        #d.msg = 'xxx'
            # #这种形式调用该对象有装饰setter的方法,xxx作为形参
        #print(d.msg)  结果:xxx
 
 
class GCDViewer(object):
    '''
    共军被观察者
    '''
    def update(self,observer_subject):
        print("共军:收到[%s]消息[%s] "%(observer_subject.name,observer_subject.msg) )
 
class GMDViewer(object):
    '''
    国军被观察者
    '''
    def update(self,observer_subject):
        print("国军:收到[%s]消息[%s] "%(observer_subject.name,observer_subject.msg) )
 
 
if __name__ == "__main__":
    observer1 = Observer("共军放哨者")
    observer2 = Observer("国军放哨者")
 
    gongjun1 = GCDViewer()
    guojun1 = GMDViewer()
 
    observer1.attach(gongjun1)
    observer1.attach(guojun1)
 
 
    observer2.attach(guojun1)
 
    observer1.msg = "\033[32;1m敌人来了...\033[0m"
 
 
    observer2.msg ="\033[31;1m前方发现敌人,请紧急撤离,不要告诉共军\033[0m"

1.3.2 状态模式–State

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

1.3.3 策略模式–Strategy

'''
Strategy
'''
class TravelStrategy(object):
    '''
    出行策略
    '''
 
    def travelAlgorithm(self):
        pass
 
class AirplaneStrategy(TravelStrategy):
    def travelAlgorithm(self):
        print("坐飞机出行....")
 
class TrainStrategy(TravelStrategy):
    def travelAlgorithm(self):
        print("坐高铁出行....")
 
 
class CarStrategy(TravelStrategy):
    def travelAlgorithm(self):
        print("自驾出行....")
 
class BicycleStrategy(TravelStrategy):
    def travelAlgorithm(self):
        print("骑车出行....")
 
 
class TravelInterface(object):
    def __init__(self,travel_strategy):
        self.travel_strategy = travel_strategy
 
    def set_strategy(self,travel_strategy):
        self.travel_strategy = travel_strategy
    def travel(self):
        return self.travel_strategy.travelAlgorithm()
 
 
 
#坐飞机
travel = TravelInterface(AirplaneStrategy())
 
travel.travel()
 
#改开车
travel.set_strategy(CarStrategy())
travel.travel()

1.3.4 职责链模式–Chain of Responsibility

'''
Chain of Responsibility
'''
 
 
# 职责链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
# 适用场景:
# 1、有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定;
# 2、在不明确指定接收者的情况下,向多个对象中的一个提交一个请求;
# 3、处理一个请求的对象集合应被动态指定。
 
class BaseHandler(object):
    '''处理基类'''
 
 
    def successor(self,successor): #next_handler
        #与下一个责任者关联
        self._successor = successor
 
class RequestHandlerL1(BaseHandler):
    '''第一级请求处理者'''
    name = "TeamLeader"
    def handle(self,request):
        if request < 500 :
            print("审批者[%s],请求金额[%s],审批结果[审批通过]"%(self.name,request))
        else:
            print("\033[31;1m[%s]无权审批,交给下一个审批者\033[0m" %self.name)
            self._successor.handle(request)
 
class RequestHandlerL2(BaseHandler):
    '''第二级请求处理者'''
    name = "DeptManager"
    def handle(self,request):
        if request < 5000 :
            print("审批者[%s],请求金额[%s],审批结果[审批通过]"%(self.name,request))
        else:
            print("\033[31;1m[%s]无权审批,交给下一个审批者\033[0m" %self.name)
            self._successor.handle(request)
 
class RequestHandlerL3(BaseHandler):
    '''第三级请求处理者'''
    name = "CEO"
    def handle(self,request):
        if request < 10000 :
            print("审批者[%s],请求金额[%s],审批结果[审批通过]"%(self.name,request))
        else:
            print("\033[31;1m[%s]要太多钱了,不批\033[0m"%self.name)
            #self._successor.handle(request)
 
class RequestAPI(object):
    h1 = RequestHandlerL1()
    h2 = RequestHandlerL2()
    h3 = RequestHandlerL3()
 
    h1.successor(h2)
    h2.successor(h3)
    def __init__(self,name,amount):
        self.name = name
        self.amount = amount
 
 
 
    def handle(self):
 
        '''统一请求接口'''
        self.h1.handle(self.amount)
 
 
if __name__ == "__main__":
    r1 = RequestAPI("Burgess",8000)
    r1.handle()
    print(r1.__dict__)

1.3.5 命令模式–Command

 
"""
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', 'foo1.txt'))
    command_stack.append(MoveFileCommand('bar.txt', 'bar1.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()

1.3.6 访问模式–Visitor

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

1.3.7 调停者模式–Mediator

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

1.3.8 备忘录模式–Memento

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

1.3.9 迭代器模式–Iterator

 
'''
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 = count_to(2)
count_to_five = 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(" ")

1.3.10 解释器模式–Interpreter

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

1.3.11 模版方法–Template Method

 
'''
Template Method
'''
# 模板方法模式概述
#        在现实生活中,很多事情都包含几个实现步骤,例如请客吃饭,无论吃什么,一般都包含点单、吃东西、买单等几个步骤,通常情况下这几个步骤的次序是:点单 --> 吃东西 --> 买单。在这三个步骤中,点单和买单大同小异,最大的区别在于第二步——吃什么?吃面条和吃满汉全席可大不相同,如图1所示:
#
# 图1 请客吃饭示意图
#         在软件开发中,有时也会遇到类似的情况,某个方法的实现需要多个步骤(类似“请客”),其中有些步骤是固定的(类似“点单”和“买单”),而有些步骤并不固定,存在可变性(类似“吃东西”)。为了提高代码的复用性和系统的灵活性,可以使用一种称之为模板方法模式的设计模式来对这类情况进行设计,在模板方法模式中,将实现功能的每一个步骤所对应的方法称为基本方法(例如“点单”、“吃东西”和“买单”),而调用这些基本方法同时定义基本方法的执行次序的方法称为模板方法(例如“请客”)。在模板方法模式中,可以将相同的代码放在父类中,例如将模板方法“请客”以及基本方法“点单”和“买单”的实现放在父类中,而对于基本方法“吃东西”,在父类中只做一个声明,将其具体实现放在不同的子类中,在一个子类中提供“吃面条”的实现,而另一个子类提供“吃满汉全席”的实现。通过使用模板方法模式,一方面提高了代码的复用性,另一方面还可以利用面向对象的多态性,在运行时选择一种具体子类,实现完整的“请客”方法,提高系统的灵活性和可扩展性。
#        模板方法模式定义如下:
# 模板方法模式:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
#
# Template Method Pattern:  Define the skeleton of an algorithm in an  operation, deferring some steps to subclasses. Template Method lets  subclasses redefine certain steps of an algorithm without changing the  algorithm's structure.
#        模板方法模式是一种基于继承的代码复用技术,它是一种类行为型模式。
#        模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。模板方法模式提供了一个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。
#
 
class Register(object):
    '''用户注册接口'''
 
    def register(self):
        pass
    def login(self):
        pass
 
    def auth(self):
        self.register()
        self.login()
 
class RegisterByQQ(Register):
    '''qq注册'''
 
    def register(self):
        print("---用qq注册-----")
 
    def login(self):
        print('----用qq登录-----')
 
 
 
class RegisterByWeiChat(Register):
    '''微信注册'''
 
    def register(self):
        print("---用微信注册-----")
 
    def login(self):
        print('----用微信登录-----')
 
 
if __name__ == "__main__":
 
    register1 = RegisterByQQ()
    register1.login()
 
    register2 = RegisterByWeiChat()
    register2.login()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡侃有料

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值