• 对象类设计模式之访问者模式


    本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~

             访问者模式是一种分离对象数据和行为的方法,通过这类分离,可认为一个已存在的类或类群增加新的操纵而不用更改他们的数据。

             这个模式其实和迭代器模式在很大程度上有相似的货色,因为迭代器也是访问对象而不转变对象的元素,但是迭代器的使用范围更加单一也更具有针对性。而访问者模式能够增加对对象的操纵而不修改其数据。

             为什么要使用访问者模式?
        如何扩展一个现有的类层次结构来实现新行为?一般的方法是给类添加新的方法。但是万一新行为和现有对象模型不兼容怎么办?还有,类层次结构设计人员可能无法预知以后开发过程中将会须要哪些功能。以及,如果已有的类层次结构不允许修改代码,怎么能扩展行为呢? 这个时候,访问者就能够起到作用。

               访问者模式中的角色

        访问者抽象接口,通过visit(Element)方法访问Element(数据结构),完成对Element的操纵行为。

        详细访问者(ConcreteVisitor)访问者的详细实现类。

        元素(Element),也就是被访问者通过accept(Visitor)方法接受Visitor的访问。详细元素(ConcreteElement)  元素的详细实现类。

        对象结构(ObjectStructure)  具有一组元素的组合对象。ObjectStructure本身也可以作为被访问者。

        访问者模式的结构图如下:

        对象和类

        

                 使用访问者模式的条件

        1))须要对一个对象结构中的对象停止很多不同的并且不相关的操纵,而你想避免让这些操纵污染这些对象的类。Visitor使得你可以将相关的操纵会合起来定义在一个类中。

        2) 当该对象结构被很多应用同享时,用Visitor模式让每个应用仅包括须要用到的操纵。

        每日一道理
    成功的花朵开放在啊勤劳的枝头,失败的苦果孕育在懒惰的温床之中。

        3) 定义对象结构的类很少转变,但经常须要在此结构上定义新的操纵。转变对象结构类须要重定义对全部访问者的接口,这可能须要很大的代价。如果对象结构类经常转变,那么可能还是在这些类中定义这些操纵较好。

        从上述所讲的条件,我们知道了访问者模式其实用在最多的地方应该是扩展接口的时候。同时,我们不用每次增加操纵都定义在对象的结构外部,以免造成类结构过于臃肿。

        举一个实际的使用例子吧。

    //元素(被访问者)
    class CPerson //纯虚类
    {
    protected:
           stringname; //或者改成数组
           intgender;
     
           CPerson()
    public:
           virtual void Accept( CVisitor& ) //=0;//纯虚函数
     
    //访问者
    class CVisitor
    {
    public:
           virtual void Visit( CStudent& ) = 0;
           virtual void Visit( CTeacher& ) = 0;
    };
     
    //详细元素
    class CStudent: public CPerson
    {
    private:
           intgrade; //年级
    public:
           CStudent(stringName,int Gender,int Grade)
           {
                  name=Name;
                  gender=Gender;
                  grade=Grade;
           }
    public:
           virtual void Accept(CVisitor& printer) //虚函数
           voidSetGrade(int Grade)
           intGetGrade() const
    };
     
    //详细元素
    class CTeacher:public CPerson
    {
    private:
           intservice_time;//工龄
    public:
           CTeacher(stringName,int Grade, int ServiceTime)
           {
                  name= Name;
                  gender= Grade;
                  service_time= ServiceTime;
           }
     
    public:
           virtualvoid Accept(CVisitor& printer)
          
           voidSetServiceTime(int ServiceTime)
          
           intGetServiceTime() const
          
    };

        在上述代码中,从程序的标记处可以看得出来,访问者模式是通过同一管理对象集合中的各个类的访问,而在每个类中,均供给对象的接口一遍访问者来访问。因此,当我们每次增加一个类的操纵的时候,只须要为访问者供给一个可以操纵的接口,同事在访问者中供给一个访问接口,访问者通过访问接口,以输入参数的情势来获得对对象中的各个类的操纵,而不用修改到其中的详细元素。

        当然,有时候使用访问者模式未必是能够增加工作效率,如果对象中的这个操纵很频仍使用的话,那么最好还是封装在对象的外部中,而且如果要完全的访问对象中的元素,很可能会涉及到暴漏处对象的成员属性,对于数据封装性和安全性并非很好的方式。

    文章结束给大家分享下程序员的一些笑话语录: 警告
    有一个小伙子在一个办公大楼的门口抽着烟,一个妇女路过他身边,并对他 说, “你知道不知道这个东西会危害你的健康?我是说, 你有没有注意到香烟 盒上的那个警告(Warning)?”
    小伙子说,“没事儿,我是一个程序员”。
    那妇女说,“这又怎样?”
    程序员说,“我们从来不关心 Warning,只关心 Error”

  • 相关阅读:
    element-ui+mongodb+express项目的实现(含源代码)
    Mybatis之逆向工程的文件和方法解析
    Mybatis之逆向工程的配置和实操
    ### The error may exist in com/online/dao/BlogMapper.java (best guess)
    ### Error opening session. Cause: java.lang.NullPointerException
    mongodb下载安装和基本操作
    SSM框架的具体搭建配置
    JSON字符串多了一个等号
    JSON使用变量值作为键名
    Ajax中文乱码解决方法
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3091600.html
Copyright © 2020-2023  润新知