• 设计模式之访问器模式(Visitor)的C++实现


    1、访问器模式的提出

    在软件开发过程中,早已发布的软件版本,由于需求的变化,需要给某个类层次结构增加新的方法。如果在该基类和子类中都添加新的行为方法,将给代码原有的结构带来破坏,同时,也违反了修改封闭,扩展开放的原则。访问器模式可以实现不改变原有代码结构的前提下,基于双向分发机制(2次虚函数绑定实例对象),通过扩展的方法实现新的接口。

    2、需求描述

    有2个固定数量的元素AB,每个元素有不同方法。A、B元素的方法有可能还会更新。请设计一个功能代码,可以应对方法更新的代码。

    3、功能实现

    (1)UML图如下:

     (2)代码实现如下:

    1. #include
    2. class ConcreteElementA;
    3. class ConcreteElementB;
    4. class Visitor
    5. {
    6. public:
    7. virtual void visitorElementA(ConcreteElementA& element)=0; //第二次虚函数
    8. virtual void visitorElementB(ConcreteElementB& element)=0;
    9. };
    10. class Element
    11. {
    12. public:
    13. virtual void accept(Visitor& visitor)=0; //第一次虚函数
    14. virtual ~Element(){};
    15. };
    16. class ConcreteElementA:public Element
    17. {
    18. public:
    19. void accept(Visitor &visitor) override
    20. {
    21. visitor.visitorElementA(*this);
    22. }
    23. };
    24. class ConcreteElementB:public Element
    25. {
    26. public:
    27. void accept(Visitor &visitor) override
    28. {
    29. visitor.visitorElementB(*this);
    30. }
    31. };
    32. // 上面是稳定的代码结构
    33. // 下面是扩展应对方法改变的功能类
    34. class ConcreteVisitor1:public Visitor
    35. {
    36. public:
    37. void visitorElementA(ConcreteElementA &element) override
    38. {
    39. std::cout << "Visitor1 process visitorElementA "<< &element << std::endl;
    40. }
    41. void visitorElementB(ConcreteElementB &element) override
    42. {
    43. std::cout << "Visitor1 process visitorElementB " << &element << std::endl;
    44. }
    45. };
    46. class ConcreteVisitor2:public Visitor
    47. {
    48. public:
    49. void visitorElementA(ConcreteElementA &element) override
    50. {
    51. std::cout << "Visitor2 process visitorElementA " << &element<< std::endl;
    52. }
    53. void visitorElementB(ConcreteElementB &element) override
    54. {
    55. std::cout << "Visitor2 process visitorElementB " << &element << std::endl;
    56. }
    57. };
    58. class Client{
    59. public:
    60. void doWork()
    61. {
    62. ConcreteVisitor1 visitor1;
    63. ConcreteElementA element1A;
    64. element1A.accept(visitor1);
    65. ConcreteElementB element1B;
    66. element1B.accept(visitor1);
    67. ConcreteVisitor2 visitor2;
    68. ConcreteElementA element2A;
    69. element2A.accept(visitor2);
    70. ConcreteElementB element2B;
    71. element2B.accept(visitor2);
    72. }
    73. };
    74. int main()
    75. {
    76. Client obj;
    77. obj.doWork();
    78. return 0;
    79. }

    程序运行的结果如下:

     上面的代码,ConcreteElementA和ConcreteElementB的方法更新,通过Visitor基类的扩展子类来实现。

    通过上面的代码可以看出,使用访问器模式的应用场景必须满足下面的条件:
    (1)Element的子类个数必须确定。
    (2)Visitor的子类必须实现Element的所有子类方法。

  • 相关阅读:
    ​金属外壳笔记本电脑会触电吗?
    2022北京健博会/北京大健康产业展览会/中国大健康博览会
    JavaScript函数
    ECCV 2022 | 知识可取可存!新加坡国立大学提出:全新可恢复型模型遗忘框架LIRF!...
    使用OpenMMLab系列的开源库时,常用的脚本合集。
    动荡的2023年
    R语言dplyr包select函数删除dataframe数据中的多个数据列(通过向量指定需要删除的数据列的集合、并且在向量的前面添加负号)
    LeetCode669. Trim a Binary Search Tree
    【vue3-element-admin】ESLint+Prettier+Stylelint+EditorConfig 约束和统一前端代码规范
    Acwing 907. 区间覆盖
  • 原文地址:https://blog.csdn.net/hanxiaoyong_/article/details/132781997