【Iterator模式】
提供了一种顺序访问一个聚合对象(aggregate)中各个元素,而又不需要暴露该对象的内部表示的。其关键是将对列表的访问和遍历从列表对象中分离出来并放入一个迭代器(iterator)对象中。迭代器定义个一个访问该列元素的接口,迭代器对象负责跟踪当前的元素;即它知道哪些元素已经遍历过了。迭代器和列表是耦合在一起的,而且客户对象必须知道遍历的是一个列表而不是其他聚合结构。STL提供了iterator来遍历各种STL中的列表。
【图解】
以aggregate维护一个简单的数组结构为例子,其相应的迭代器iterator可以对该数组进行顺序的访问。一种是通过聚合对象自身提供的创建接口(CreateIterator函数,当然也是调用迭代器的构造函数),另一种是直接调用迭代器的构造函数完成。以下例子使用了类模板的继承,在这种情况下,实现和定义最好写在一个头文件中即可(会避免带来一些的问题)。
【程序】
【输出】
【Singleton模式】
保证一个类有一个实例,并提供一个访问它的全局访问点。从而避免使用全局变量,全局变量有一系列的缺点,如内存占用生命期长,名字污染等等。
(1)最简单的单例模式在多线程环境下是线程不安全的,对此要考虑下面的两点。
想要让单例模式(singleton)在多线程环境下处于一个安全的状态需要注意,对于处于多线程环境中的类,使用单例模式要考虑如下。
(2)Windows平台上线程同步可以利用<Windows.h>中的CRITICAL_SECTION,UNIX/LINUX平台要使用到<pthread.h>的线程同步机制,这些机制即可可以应用于对象中“临界资源数据”。但是用于单例模式中的GetInstance函数时,由于第一次调用时,临界边量尚未初始化(构造函数尚未调用),因此给类对象的创建代码(GetInstance函数中的代码)加锁就很报一个运行时的错误,是由于临界变量的初始化是在构造函数中完成的,而此时构造函数尚未调用,所以临界变量的初始化尚未完成。因此GetInstance的实现要考虑下面的线程安全的方式。而JAVA中可能可以考虑线程synchronized GetInstance()同步的方式进行,但是创建效率可能会受到一定的影响。
(3)对于单例模式中对象实例的获取,采用“局部静态变量”是线程安全的方式。其他的static成员的临界资源的访问,则要使用加锁操作。
另外GoF中还提到了"单件注册表"来解决Singleton类的子类的创建的问题。这里不细说了,有兴趣查书。
【图解】
给出线程安全解释的图例,类图就没什么必要了。
【程序】
(1)线程不安全的单件模式
(2)线程安全的单件模式[采用局部静态方式,同时给出临界资源的加锁机制(Windows的,Linux的要用pthread中的东西)]
(3)Main函数调用,具体的多线程的调用就不细说了。主要是Singleton模式本身。
【输出】
可以看出地址指向的是同一个对象。局部静态的方式创建的单件模式对象,最后的析构函数被显示调用了。