• 迭代器模式c++实现


    参考书籍《Head First设计模式》

    需求场景

               餐馆和咖啡馆的菜单分别是用数组和容器(vector)存储的,有一天餐馆和咖啡店合并了想要打印菜单,必须实现两个不同的遍历(数组用sizeof计算长度,用[]取元素;容器用size取长度,用at()取元素),来处理两种不同的聚合类型,代码类似于下面所示

     

    1. for (int i = 0; i<sizeof(dinerMenu.items_) / sizeof(dinerMenu.items_[0]); i++)
    2. {
    3. MenuItem item = dinerMenu.items_[i];
    4. std::cout << item.name <<","<< item.description << ","<< item.price << std::endl;
    5. }
    6. for (int i = 0; isize(); i++)
    7. {
    8. MenuItem item = conffeMenu.items_.at(i);
    9. std::cout << item.name << "," << item.description << "," << item.price <
    10. }

           如果我们还要遍历另外一种聚合数据,比如map,那么就要再加一种遍历方法。又或者我们有一天咖啡店不用容器存储,改用数组了,那我们的遍历方法又要改写。这就要求客户端对聚合的实现很了解,即针对实现编程(而我们提倡的设计原则是针对接口编程,而不是针对实现编程)。

         在上述例子中引起变化的是:由不同的组合类型所造成的遍历。那我们可以封装遍历吗?迭代器模式就是封装了遍历。迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

    模式定义

            迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。

    迭代器模式让我们能游走于聚合内的每一个元素,而又不暴露其内部表示。

            类图如下

            


           

    代码实现

             

             如上面需求场景中,我们使用迭代器模式,让两个具体的聚合类(餐馆和咖啡馆)都提供一个createIterator的接口,客户端使用该接口返回的iterator遍历聚合体中各元素。这样客户端不需要关系聚合体的具体实现,针对不同聚合体提供的iterator使用方法一样。

             先定义迭代器接口(抽象类Iterator)

         

    1. class Iterator {
    2. public:
    3. virtual bool hasNext() = 0;
    4. virtual void* next() = 0;
    5. };

    两个具体的迭代器:餐厅菜单迭代器和咖啡店菜单迭代器

    1. class CoffeMenuIterator :public Iterator {
    2. public:
    3. CoffeMenuIterator(std::vector< MenuItem>* items) :items_(items), position_(0)
    4. {
    5. }
    6. virtual MenuItem& next()override
    7. {
    8. MenuItem& item = items_->at(position_);
    9. position_++;
    10. return item;
    11. }
    12. bool hasNext()override
    13. {
    14. if (position_ >= items_->size())
    15. {
    16. return false;
    17. }
    18. else
    19. {
    20. return true;
    21. }
    22. }
    23. private:
    24. std::vector< MenuItem>* items_;
    25. int position_;
    26. };
    27. class DinerMenuIterator :public Iterator {
    28. public:
    29. DinerMenuIterator(MenuItem items[],int length) :items_(items), position_(0),length_(length)
    30. {
    31. }
    32. virtual MenuItem& next()override
    33. {
    34. MenuItem& item = items_[position_];
    35. position_++;
    36. return item;
    37. }
    38. bool hasNext()override
    39. {
    40. if (position_ >= length_)
    41. {
    42. return false;
    43. }
    44. else
    45. {
    46. return true;
    47. }
    48. }
    49. private:
    50. MenuItem* items_;
    51. int position_;
    52. int length_;
    53. };

            再实现两个具体的聚合类,针对该例子即实现餐馆菜单和咖啡店菜单(它们都要实现createIterator接口)。

    1. class Menu {
    2. public:
    3. virtual Iterator* createIterator() = 0;
    4. };
    5. class DinerMenu :public Menu {
    6. public:
    7. DinerMenu()
    8. {
    9. items_[0] = { "红烧肉","红烧肉,肥瘦相间,香而不腻",32 };
    10. items_[1] = { "西红柿炒鸡蛋","西红柿炒鸡蛋,国民妈妈菜",15 };
    11. items_[2] = { "土豆丝","土豆丝,超便宜",12 };
    12. }
    13. virtual Iterator* createIterator() override {
    14. return new DinerMenuIterator(items_,3);
    15. }
    16. private:
    17. MenuItem items_[3];
    18. };
    19. class CoffeMenu :public Menu {
    20. public:
    21. CoffeMenu()
    22. {
    23. items_.push_back({ "拿铁","拿铁,好喝",18 });
    24. items_.push_back({ "卡布奇诺","卡布奇诺卡布奇诺",18 });
    25. items_.push_back({ "意式浓缩咖啡","意式浓缩咖啡",22 });
    26. }
    27. virtual Iterator* createIterator() override {
    28. return new CoffeMenuIterator(&items_);
    29. }
    30. private:
    31. std::vector< MenuItem> items_;
    32. };

       运行测试效果如下

       

            


           

  • 相关阅读:
    使用openssl生成SAN证书 多个注意点
    PostgreSQL10安装postgis插件
    MySQL 主从复制与读写分离
    python 将一列文本或字符串调整成一行 中间用逗号 单引号分隔
    使用数字孪生实现电池管理系统 (BMS) 测试自动化
    双一流高校全球通邮经验:Coremail安全海外中继提升科研效率
    杰理之发射 SDK 接收模式添加读卡器功能(自定义 USB 设备描述符)【篇】
    GBASE 8A v953报错集锦28--使用企业管理器执行 select count(1) into @c from t1;报错
    使用Spring Boot双数据源和PageHelper实现无缝分页查询
    Java 异常中 e.getMessage() 和 e.toString() e.printStackTrace()的区别
  • 原文地址:https://blog.csdn.net/sinat_41928334/article/details/126332641