面向对象的设计模式3

行为型模式

  ■责任链模式

  ■迭代器模式

  ■观察者模式

  ■策略模式

  ■模板方法模式

 

1.责任链模式

 

 

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


#--高级例子--模仿js事件处理

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)





a['event_handler'].handle()

2.迭代器模式

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

实现方法:__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))

3.观察者模式

内容:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。观察者模式又称“发布-订阅”模式
角色:
  抽象主题(Subject)
  具体主题(ConcreteSubject)——发布者
  抽象观察者(Observer)
  具体观察者(ConcreteObserver)——订阅者
当一个抽象模型有两方面,其中一个方面依赖于另一个方面。将这两者封装在独立对象中以使它们可以各自独立地改变和复用。
当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。
优点:
  目标和观察者之间的抽象耦合最小
  支持广播通信
缺点:
  多个观察者之间互不知道对方存在,因此一个观察者对主题的修改可能造成错误的更新。
# coding : utf-8
# create by ztypl 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)

4.策略模式

内容:定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
角色:
  抽象策略(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()

5.模板方法模式


内容:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
角色:
  抽象类(AbstractClass):定义抽象的原子操作(钩子操作);实现一个模板方法作为算法的骨架。
  具体类(ConcreteClass):实现原子操作
适用场景:
  一次性实现一个算法的不变的部分
  各个子类中的公共行为应该被提取出来并集中到一个公共父类中以避免代码重复
  控制子类扩展
# coding : utf-8
# create by ztypl 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):
 

 

 

原文地址:https://www.cnblogs.com/ldq1996/p/8409762.html