zoukankan      html  css  js  c++  java
  • 设计模式三:行为型模式

    一、责任链模式

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

    角色:

    抽象处理者(Handler)

    具体处理者(ConcreteHandler)

    客户端(Client)

    例:

    请假部门批准:leader-->部门经理--->总经理

    Javascript事件浮升机制

    适用场景

    有多个对象可以处理一个请求,哪个对象处理由运行时决定

    在不明确接收者的情况下,向多个对象中的一个提交一个请求

    优点:

    降低耦合度:一个对象无需知道是其他哪一个对象处理其请求

    缺点:

    请求不保证被接收:链的末端没有处理或链配置错误

    # coding : utf-8
    # create by ztypl on 2017/5/27
    
    from abc import ABCMeta, abstractmethod
    
    class Handler(metaclass=ABCMeta):
        @abstractmethod
        def handle_leave(self, day):
            pass
    
    
    class GeneralManagerHandler(Handler):
        def handle_leave(self, day):
            if day < 10:
                print("总经理批准%d天假"%day)
            else:
                print("呵呵")
    
    
    class DepartmentManagerHandler(Handler):
        def __init__(self):
            self.successor = GeneralManagerHandler()
        def handle_leave(self, day):
            if day < 7:
                print("部门经理批准%d天假"%day)
            else:
                print("部门经理无权准假")
                self.successor.handle_leave(day)
    
    
    class ProjectDirectorHandler(Handler):
        def __init__(self):
            self.successor = DepartmentManagerHandler()
        def handle_leave(self, day):
            if day < 3:
                print("项目主管批准%d天假")
            else:
                print("项目主管无权准假")
                self.successor.handle_leave(day)
    
    
    day = 4
    h = ProjectDirectorHandler()
    h.handle_leave(day)
    请假示例
    class Handler(metaclass=ABCMeta):
        @abstractmethod
        def add_event(self, func):
            pass
    
        @abstractmethod
        def handle(self):
            pass
    
    
    class BodyHandler(Handler):
        def __init__(self):
            self.func = None
    
        def add_event(self, func):
            self.func = func
    
        def handle(self):
            if self.func:
                return self.func()
            else:
                print("已到最后一级,无法处理")
    
    
    class ElementHandler(Handler):
        def __init__(self, successor):
            self.func = None
            self.successor = successor
    
        def add_event(self, func):
            self.func = func
    
        def handle(self):
            if self.func:
                return self.func()
            else:
                return self.successor.handle()
    
    
    # 客户端
    
    # <body><div><a>
    
    body = {'type': 'body', 'name': 'body', 'children': [], 'father': None}
    
    div = {'type': 'div', 'name': 'div', 'children': [], 'father': body}
    
    a = {'type': 'a', 'name': 'a', 'children': [], 'father': div}
    
    body['children'].append(div)
    div['children'].append(a)
    
    body['event_handler'] = BodyHandler()
    div['event_handler'] = ElementHandler(div['father']['event_handler'])
    a['event_handler'] = ElementHandler(a['father']['event_handler'])
    
    
    def attach_event(element, func):
        element['event_handler'].add_event(func)
    
    #test
    
    def func_div():
        print("这是给div的函数")
    
    def func_a():
        print("这是给a的函数")
    
    def func_body():
        print("这是给body的函数")
    
    #attach_event(div, func_div)
    #attach_event(a, func_a)
    #attach_event(body, func_body)
    高级例子--模仿js事件处理

    二、迭代器模式

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

    实现方法:__iter__、__next__

    # coding : utf-8
    # create by ztypl on 2017/5/27
    
    
    class LinkList:
        """链表 头结点保存链表的长度"""
        class Node:
            def __init__(self, item=None):
                self.item = item
                self.next = None
    
        class LinkListIterator:
            def __init__(self, node):
                self.node = node
            def __next__(self):
                if self.node:
                    cur_node = self.node
                    self.node = cur_node.next
                    return cur_node.item
                else:
                    raise StopIteration
            def __iter__(self):
                return self
    
        def __init__(self, iterable=None):
            self.head = LinkList.Node(0)
            self.tail = self.head
            self.extend(iterable)
    
        def append(self, obj):
            s = LinkList.Node(obj)
            self.tail.next = s
            self.tail = s
    
        def extend(self, iterable):
            for obj in iterable:
                self.append(obj)
            self.head.item += len(iterable)
    
        def __iter__(self):
            return self.LinkListIterator(self.head.next)
    
        def __len__(self):
            return self.head.item
    
        def __str__(self):
            return "<<"+", ".join(map(str, self))+">>"
    
    
    
    li = [i for i in range(100)]
    print(li)
    lk = LinkList(li)
    # for i in lk:
    #     print(i)
    
    print(lk)
    # print(len(lk))
    View Code

    三、观察者模式

    定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。观察者模式又称“发布-订阅”模式

    角色:

    抽象主题(Subject)

    具体主题(ConcreteSubject)——发布者

    抽象观察者(Observer)

    具体观察者(ConcreteObserver)——订阅者

    适用场景

    当一个抽象模型有两方面,其中一个方面依赖于另一个方面。将这两者封装在独立对象中以使它们可以各自独立地改变和复用。

    当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。

    当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。

    优点:

    目标和观察者之间的抽象耦合最小 支持广播通信

    缺点

    多个观察者之间互不知道对方存在,因此一个观察者对主题的修改可能造成错误的更新

    # coding : utf-8
    # create by ctz on 2017/5/27
    
    from abc import ABCMeta, abstractmethod
    
    
    class Observer(metaclass=ABCMeta):
        @abstractmethod
        def update(self, notice):
            pass
    
    
    class Notice:
        def __init__(self):
            self.observers = [] # 记录该主体的观察者(订阅者)
    
        def attach(self, obs):
            self.observers.append(obs)
    
        def detach(self, obs):
            obs.company_info = None
            self.observers.remove(obs)
    
        def notify(self):
            for obj in self.observers:
                obj.update(self)
    
    
    class ManagerNotice(Notice):
        def __init__(self, company_info=None):
            super().__init__()
            self.__company_info = company_info
    
        @property
        def company_info(self):
            return self.__company_info
    
        @company_info.setter
        def company_info(self, info):
            self.__company_info = info
            self.notify()
    
    
    
    class Manager(Observer):
        def __init__(self):
            self.company_info = None
    
        def update(self, noti):
            self.company_info = noti.company_info
    
    
    notice = ManagerNotice()
    
    alex = Manager()
    wusir = Manager()
    
    # print(alex.company_info)
    # print(wusir.company_info)
    
    notice.attach(alex)
    notice.attach(wusir)
    #
    notice.company_info="公司运行良好"
    #
    print(alex.company_info)
    print(wusir.company_info)
    #
    notice.detach(wusir)
    #
    notice.company_info="公司要破产了"
    
    print(alex.company_info)
    print(wusir.company_info)
    View Code

    四、策略模式

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

    角色:

    抽象策略(Strategy)

    具体策略(ConcreteStrategy)

    上下文(Context)

    适用场景

    许多相关的类仅仅是行为有异

    需要使用一个算法的不同变体

    算法使用了客户端无需知道的数据

    一个类中的多种行为以多个条件语句的形式存在,可以将这些行为封装如不同的策略类中。

    优点:

    定义了一系列可重用的算法和行为

    消除了一些条件语句

    可以提供相同行为的不同实现

    缺点:

    客户必须了解不同的策略

    策略与上下文之间的通信开销

    增加了对象的数目

    # coding : utf-8
    # create by ztypl on 2017/5/27
    
    from abc import ABCMeta, abstractmethod
    import random
    
    class Sort(metaclass=ABCMeta):
        @abstractmethod
        def sort(self, data):
            pass
    
    
    class QuickSort(Sort):
        def quick_sort(self, data, left, right):
            if left < right:
                mid = self.partition(data, left, right)
                self.quick_sort(data, left, mid - 1)
                self.quick_sort(data, mid + 1, right)
    
        def partition(self, data, left, right):
            tmp = data[left]
            while left < right:
                while left < right and data[right] >= tmp:
                    right -= 1
                data[left] = data[right]
                while left < right and data[left] <= tmp:
                    left += 1
                data[right] = data[left]
            data[left] = tmp
            return left
    
        def sort(self, data):
            print("快速排序")
            return self.quick_sort(data, 0, len(data) - 1)
    
    
    class MergeSort(Sort):
        def merge(self, data, low, mid, high):
            i = low
            j = mid + 1
            ltmp = []
            while i <= mid and j <= high:
                if data[i] <= data[j]:
                    ltmp.append(data[i])
                    i += 1
                else:
                    ltmp.append(data[j])
                    j += 1
    
            while i <= mid:
                ltmp.append(data[i])
                i += 1
    
            while j <= high:
                ltmp.append(data[j])
                j += 1
    
            data[low:high + 1] = ltmp
    
    
        def merge_sort(self, data, low, high):
            if low < high:
                mid = (low + high) // 2
                self.merge_sort(data, low, mid)
                self.merge_sort(data, mid + 1, high)
                self.merge(data, low, mid, high)
    
        def sort(self, data):
            print("归并排序")
            return self.merge_sort(data, 0, len(data) - 1)
    
    
    class Context:
        def __init__(self, data, strategy=None):
            self.data = data
            self.strategy = strategy
    
        def set_strategy(self, strategy):
            self.strategy = strategy
    
        def do_strategy(self):
            if self.strategy:
                self.strategy.sort(self.data)
            else:
                raise TypeError
    
    
    li = list(range(100000))
    random.shuffle(li)
    
    context = Context(li, MergeSort())
    context.do_strategy()
    #print(context.data)
    
    random.shuffle(context.data)
    
    context.set_strategy(QuickSort())
    context.do_strategy()
    View Code

    五、模板方法模式

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

    角色:

    抽象类(AbstractClass):定义抽象的原子操作(钩子操作);实现一个模板方法作为算法的骨架。

    具体类(ConcreteClass):实现原子操作

    适用场景

    一次性实现一个算法的不变的部分

    各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复

    控制子类扩展

     

    # coding : utf-8
    # create by ctz on 2017/5/27
    
    from abc import ABCMeta, abstractmethod
    
    
    class IOHandler(metaclass=ABCMeta):
        @abstractmethod
        def open(self, name):
            pass
        @abstractmethod
        def deal(self, change):
            pass
        @abstractmethod
        def close(self):
            pass
        def process(self, name, change):
            self.open(name)
            self.deal(change)
            self.close()
    
    
    class FileHandler(IOHandler):
    View Code
  • 相关阅读:
    【leetcode】1403. Minimum Subsequence in Non-Increasing Order
    【leetcode】1399. Count Largest Group
    【leetcode】1396. Design Underground System
    【leetcode】1395. Count Number of Teams
    【leetcode】1394. Find Lucky Integer in an Array
    【leetcode】1391. Check if There is a Valid Path in a Grid
    【leetcode】1390. Four Divisors
    【leetcode】1389. Create Target Array in the Given Order
    modelsim仿真基本流程
    Quartus调用MOdelsim仿真过程
  • 原文地址:https://www.cnblogs.com/lianxuebin/p/8663913.html
Copyright © 2011-2022 走看看