visitor 模式

visitor 模式考虑一下设计一个可以包含长方形 正方形 圆形以及文字的视图类 因为视图中每种元素的显示方式都不一样 所以我们很容易做出如下的设计 nbsp nbsp nbsp nbsp 在这里 我使用了 COMPOSITE 模式 对于 COMPOSITE 模式 可以参考我那篇 重读 设计模式 之学习笔记 五 我对 COMPOSITE 模式的理解 nbsp nbsp nbsp nbsp 现在 我们来分析一下上面的这个设计方案 如果说 由于客户需求的改变 视图中每个元素的显示方

考虑一下设计一个可以包含长方形、正方形、圆形以及文字的视图类。因为视图中每种元素的显示方式都不一样,所以我们很容易做出如下的设计:

visitor 模式

class
 CVisitor
{



public
:
    

virtual
 
~
CVisitor();
    

virtual
 
void
 VisitRectangle(CTRectangle 
*
pRectangle) 
=
 
0
;
    

virtual
 
void
 VisitSquare(CTSquare 
*
pSquare) 
=
 
0
;
    

virtual
 
void
 VisitCircle(CTCircle 
*
pCircle) 
=
 
0
;
    

virtual
 
void
 VisitText(CTText 
*
pText) 
=
 
0
;
    

virtual
 
void
 VisitView(CTView 
*
pView) 
=
 
0
;
};
class
 CContext
{



public
:
    

virtual
 
~
CContext();
    

virtual
 
void
 Accept(CVisitor
&
 v) 
=
 
0
;
};





class
 CTRectangle : 
public
 CContext
{



public
:
    

void
 Accept(CVisitor
&
 v) { v.VisitRectangle(
this
); };
};





class
 CTSquare : 
public
 CContext
{



public
:
    

void
 Accept(CVisitor
&
 v) { v.VisitSquare(
this
); };
};





class
 CTCircle : 
public
 CContext
{



public
:
    

void
 Accept(CVisitor
&
 v) { v.VisitCircle(
this
); };
};



class
 CTText : 
public
 CContext
{



public
:
    

void
 Accept(CVisitor
&
 v) { v.VisitText(
this
); };
};





class
 CTView : 
public
 CContext
{



public
:
    

~
CTView();
    

void
 Accept(CVisitor
&
 v);
    

void
 Add(CContext 
*
pContext);



private
:
    vector

<
CContext
*>
 m_vContext;
};

CTView::



~
CTView()
{

    


while
(
!
m_vContext.empty())
    {

        CContext 


*
pContext 
=
 (CContext
*
)m_vContext.back();
        m_vContext.pop_back();

        delete pContext;
    }
}








void
 CTView::Accept(CVisitor
&
 v)
{

    


for
(vector
<
CContext
*>
::iterator i 
=
 m_vContext.begin(); i 
!=
 m_vContext.end(); 
++
i)
    {

        (


*
i)
->
Accept(v);
    }
    v.VisitView(


this
);
}




void
 CTView::Add(CContext
*
 pContext)
{

    m_vContext.push_back(pContext);
}


    下面,我们为上面的类添加一个显示视图中各个元素并且计算各个元素个数的visitor:

class
 CShowContextVisitor : 
public
 CVisitor
{



public
:
    CShowContextVisitor();

    



void
 VisitRectangle(CTRectangle 
*
pRectangle);
    

void
 VisitSquare(CTSquare 
*
pSquare);
    

void
 VisitCircle(CTCircle 
*
pCircle);
    

void
 VisitText(CTText 
*
pText);
    

void
 VisitView(CTView 
*
pView);



private
:
    

int
 m_iRectangleCount;
    

int
 m_iSquareCount;
    

int
 m_iCircleCount;
    

int
 m_iTextCount;
};

CShowContextVisitor::CShowContextVisitor()
: m_iRectangleCount(




0
)
, m_iSquareCount(

0
)
, m_iCircleCount(

0
)
, m_iTextCount(

0
)
{}




//
 下面以输出一句话来代替具体的显示 




void
 CShowContextVisitor::VisitRectangle(CTRectangle 
*
pRectangle)
{

    cout 


<<
 

A Rectangle is Showed!

 
<<
 endl;

    m_iRectangleCount


++
;    
}




void
 CShowContextVisitor::VisitSquare(CTSquare 
*
pSquare)
{

    cout 


<<
 

A Square is Showed!

 
<<
 endl;

    m_iSquareCount


++
;  
}




void
 CShowContextVisitor::VisitCircle(CTCircle 
*
pCircle)
{

    cout 


<<
 

A Circle is Showed!

 
<<
 endl;

    m_iCircleCount


++
;  
}




void
 CShowContextVisitor::VisitText(CTText 
*
pText)
{

    cout 


<<
 

A Text is Showed!

 
<<
 endl;

    m_iTextCount


++
;  
}




void
 CShowContextVisitor::VisitView(CTView 
*
pView)
{

    cout 


<<
 

A View is Showed!

 
<<
 endl;
    cout 

<<
 

Rectangle count: 

 
<<
 m_iRectangleCount 
<<
 endl;
    cout 

<<
 

Square count: 

 
<<
 m_iSquareCount 
<<
 endl;
    cout 

<<
 

Circle count: 

 
<<
 m_iCircleCount 
<<
 endl;
    cout 

<<
 

Text count: 

 
<<
 m_iTextCount 
<<
 endl;
}

    我们可以用下面的测试函数来验证我们的设计是否正确:

void
 Test()
{

    CTView TestView;

    CTRectangle 




*
pRectangle 
=
 
new
 CTRectangle;
    TestView.Add(pRectangle);

    CTSquare 



*
pSquare 
=
 
new
 CTSquare;
    TestView.Add(pSquare);

    CTCircle 



*
pCircle 
=
 
new
 CTCircle;
    TestView.Add(pCircle);

    CTText 



*
pText 
=
 
new
 CTText;
    TestView.Add(pText);    

    CShowContextVisitor TestVisitor;
    TestView.Accept(TestVisitor);
}




    当然,输出跟我们期望的一样:

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=

 


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227768.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午8:35
下一篇 2026年3月16日 下午8:35


相关推荐

  • 建立数据库的方法有哪些_数据库应用原则

    建立数据库的方法有哪些_数据库应用原则1:需求分析好后,找实体,不要有所落下2:分析实体里所要涉及到的属性(比如学生,在这个数据库里我需要他的学号,但不需要他的籍贯)3:分析属性的类型,长度。要想的长远点,比如学生名字的长度,汉族一般几位就够了,可万一来个维族,那几位长度就不够用了。4:实体间的关系,要满足需求和现实5:写出关系模式6:优化关系模式(越满足后面的范式越好)7:建数据库。属性,约束等最好字母+单词(正确的),

    2026年3月3日
    6
  • ora-01006:绑定变量不存在_并非所有变量已绑定怎么解决

    ora-01006:绑定变量不存在_并非所有变量已绑定怎么解决今天碰到一个很普通的问题:ORA-01008:并非所有的变量都已绑定,看着错误的提示,总以为是自己的变量和值不是对称的,检查了很多遍,最后没撤,还是在网上搜了,搜了很多方法,都说事因为自己的变量和值没有一一对应。后来,无意看到了一句话,可能是因为变量的值是null造成的,而并非值和和变量没有一一对应。经检查发现,确实有一个值是null,不是空格,然后把值改成空格,就好了。在BS系统中,使用&nbs

    2025年9月23日
    6
  • 使用IDEA控制台中文乱码问题(已解决)

    使用IDEA控制台中文乱码问题(已解决)再一次启动项目时发现控制台中文出现乱码现象 解决了之后记录下方法 1 打开 IDEA 的安装路径 根据自己 IDEA 安装的位数在 bin 目录下找到 idea64 exe vmoptions 64 位 打开 在最后一行填加 Dfile encoding utf 8 保存 2 设置

    2026年3月27日
    2
  • 实战指南:基于OpenClaw与飞书构建全天候智能运维助手

    实战指南:基于OpenClaw与飞书构建全天候智能运维助手

    2026年3月17日
    4
  • listbox里面添加WrapPanel ,支持自适应换行[通俗易懂]

    listbox里面添加WrapPanel ,支持自适应换行[通俗易懂]listbox大家都会用,如果要让它支持换行操作还必须加上ListBox.ItemsPanelItemsPanelTemplatetoolkit:WrapPanel//ItemsPanelTemplate/ListBox.ItemsPanel但是也有问题了,必须设置WrapPanel的宽度,也就是不能自适应宽度去调整每一行的宽度,这样的后果可能会出现要么全部推在一起,要么要有横向的滚动…

    2022年7月22日
    14
  • Spring Cloud Eureka服务注册中心 多节点搭建(学习总结)

    Spring Cloud Eureka服务注册中心 多节点搭建(学习总结)一、前言:本文主要搭建SpringCloudEureka服务注册中心(多节点),本文基于SpringBoot1.5.2,SpringCloudCamden.SR6版本编写,版本不一致可能会有差异。下面就学习总结记录一下:二、搭建Eureka-Server首先,引入相应的依赖pom.xml:<?xmlversion=”1.0″encoding=”UTF-8″?…

    2022年10月8日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号