Posts 设计模式-迭代模式
Post
Cancel

设计模式-迭代模式

概念解析

迭代模式,也被称为所谓迭代器模式,其核心是实现一个迭代器,其基本两个方法:

  • 获取当前所指向的元素:current()
  • 将指针移至下一个元素:next()

迭代器的意义在于提供了一个顺序访问容器对象各个元素的方法,能够不暴露对象的内部实现。Python本身实现了迭代器方式。其设计要点为:

  • 需要了解数据结构以及可能的层次结构
  • 需要根据访问要实现的功能实现具体的功能,如:next()/previous()/current()等

其优点在于:

  • 迭代器模式能够将存储数据和便利数据两项职责分离
  • 简化了聚合数据的访问方式
  • 可支持多种不同的访问方式

其缺点在于:

  • 需要增加额外的迭代器功能实现;另外增加新的聚合类时,可能需要增加新的迭代器,增加新的方法

设计模板

设计模板,即迭代器的实现,Python其实本身就存在list之类的迭代对象,这里简单描述下具体实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class BaseIterator():
    """迭代器"""
    def __init__(self, data):
        self.__data = data
        self.to_begin()

    def to_begin(self):
        """将指针移至起始位置"""
        self.__cur_idx = -1

    def to_end(self):
        """将指针移至结尾位置"""
        self.__cur_idx = len(self.__data)

    def next(self):
        """移动至下一个元素"""
        if self.__cur_idx < len(self.__data) - 1:
            self.__cur_idx += 1
            return True
        else:
            return False

    def previous(self):
        """移动至上一个元素"""
        if self.__cur_idx > 0:
            self.__cur_idx -= 1
            return True
        else:
            return False

    def current(self):
        """获取当前元素"""
        return self.__data[self.__cur_idx] if (self.__cur_idx < len(self.__data) and self.__cur_idx >= 0) else None

实例分析

场景说明:医院的排号系统,设计两个主体:病人和医生,医生不需要关心病人的情况,只需要通知排号系统叫号就行;病人也不需要关心具体哪个医生,需要按照排号系统安排即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
class Customer():
    """客户"""
    def __init__(self, name):
        self.__name = name
        self.__num = 0
        self.__clinics = None

    def get_name(self):
        return self.__name

    def register(self, system):
        system.pushCustomer(self)

    def set_num(self, num):
        self.__num = num

    def get_num(self):
        return self.__num

    def set_clinic(self, clinic):
        self.__clinics = clinic

    def get_clinic(self):
        return self.__clinics


class NumerlIterator:
    """迭代器"""
    def __init__(self, data):
        self.__data = data
        self.__cur_idx = -1

    def next(self):
        """移动至下一个元素"""
        if self.__cur_idx < len(self.__data) - 1:
            self.__cur_idx += 1
            return True
        else:
            return False

    def current(self):
        """获取当前元素"""
        return self.__data[self.__cur_idx] if (self.__cur_idx < len(self.__data) and self.__cur_idx >= 0) else None


class NumeralSystem():
    """排号系统"""
    __clinics = ("1号诊室", "二号诊室", "三号诊室")

    def __init__(self, name):
        self.__customers = []
        self.__cur_name = 0
        self.__name = name

    def push_customer(self, customer):
        customer.set_num(self.__cus_num + 1)
        click = NumeralSystem.__clinics[self._curNum % len(NumeralSystem.__clinics)]
        customer.set_clinic(click)
        self.__cur_num += 1
        self.__customer.append(customer)
        print("%s 您好!您已在%s成功挂号,序号:%04d,请耐心等待!"  %
              (customer.get_name(), self.__name, customer.get_name()))

    def get_iterator(self):
        return NumeralIterator(self.__curtomers)


# 测试代码
def testHospital():
    numeralSystem = NumeralSystem("挂号台")
    lily = Customer("Lily")
    lily.register(numeralSystem)
    pony = Customer("Pony")
    pony.register(numeralSystem)
    nick = Customer("Nick")
    nick.register(numeralSystem)
    tony = Customer("Tony")
    tony.register(numeralSystem)

    iterator = numeralSystem.get_iterator()
    while iterator.next():
        customer = iterator.current()
        print(
            "下一位病人 %04d(%s) 请到 %s 就诊。"
            % (customer.get_num(), customer.get_name(), customer.get_clinic())
        )

    """
    测试结果:
    Lily 您好!您已在挂号台成功挂号,序号:0001,请耐心等待!
    Pony 您好!您已在挂号台成功挂号,序号:0002,请耐心等待!
    Nick 您好!您已在挂号台成功挂号,序号:0003,请耐心等待!
    Tony 您好!您已在挂号台成功挂号,序号:0004,请耐心等待!

    下一位病人0001(Lily)请到1号诊室就诊。
    下一位病人0002(Pony)请到2号诊室就诊。
    下一位病人0003(Nick)请到3号诊室就诊。
    下一位病人0001(Tony)请到1号诊室就诊。
    """
This post is licensed under CC BY 4.0 by the author.

设计模式-组合模式

设计模式-外观模式