返回   cpper编程论坛 > 技术杂烩
注册账号 论坛帮助 会员列表 日历事件 搜索 今日新帖 标记版面已读

技术杂烩 找不到地方的技术问题?这里!

回复
 
LinkBack 主题工具 显示模式
  #1 (permalink)  
旧 2002-09-12
abp 的头像
abp abp 当前离线
高级会员
 
注册日期: 2002-08-30
帖子: 811
abp 正向着好的方向发展
默认 visitor

我本来想写成一篇文章的,一来没时间,二来文章缺乏交互性,而且也觉得有建立一个独立的设计模式栏目的必要,就让它作为第一个帖子吧。
我们在编写一个新的程序的时候,总会遇到需要对已有的类进行扩展的情况。譬如说,如果我们有一个类体系,Shape是所有图形的基类;他有两个子类:Rectangle和Circle,分别表示正方形和圆形。Shape包括两个函数:Draw和Move。当然,作为一个图形基类,还应该包括更多的功能,但是我们知道,我们现在无论如何都不可能预知所有的功能。也就是说,我们必须为未来的扩展作准备。大家都知道,在现有的类层次结构比较稳定的话,可以使用visitor这个设计模式来在类层次以外扩展功能。
visitor的核心是一个基类和一个虚函数。也就是:
声明一个独立于类体系的类Visit,为类体系中的每一个类加入一个纯虚函数,如:virtual void Visit(Rectangle&); virtual void Visit(Circle&);
在类层次的每个类中加入一个虚函数:virtual void Accept(Visit& v); 其实现很简单:v.Visit(*this);
visitor是通过什么机制来使得每个类能够调用相应的函数的呢?
譬如说我要实现一个功能:把一个列表中的每个Shape移动到一个新的位置(根据不同的形状有不同的计算方法),然后重画它。我可以从Visit派生一个新的类:SpecialMoveShape,它的功能为:
代码:
class SpecialMoveShape:public Visitor { virtual void Visit(Rectangle& rect) { // 先根据这个Rectangle计算移动多少 // 因为我们知道这是一个Rectangle,我们可以调用Rectangle独有的函数。譬如getSize,... rect.Move(); rect.Draw(); } // 其余函数实现略过... };
假设p是一个Shape&,但是实际上指向一个Rectangle,我们声明一个SpecialMoveShape的对象v,然后调用p.Accept(v)。由于Accept是个虚函数,最终将调用到Rectangle::Accept,然后调用v.Visit(*this);因为this的类型是Rectangle*,而v正好有一个函数Visit(Rectangle&),所以最终它将被调用,实现了针对Rectangle进行移动并重画的功能。其实,我们声明的这个类SpecialMoveShape等于在Shape类中加入了一个SpecialMove纯虚函数。
顺便说一句,visitor把本来应该在类体系的内部实现的功能转移到类体系的外部来实现,其实它和很多其它的模式一样,体现了一种理念:如果程序要完成一个功能,那么它必然在这个程序的某个地方被实现。或是在常见的地方,或是在不常见的地方。我们学习很多设计模式的目的就是能够自如的把我们想要实现的功能实现在合适的地方。
下面是示例代码,其中加注释的部分是加入一个新的类:Triangle以后做的改动。
visitor.h
代码:
#ifndef __A0CC449E0FC0993D677D76384ECE93051C2525CA76E1FAE__ #define __A0CC449E0FC0993D677D76384ECE93051C2525CA76E1FAE__ #include <iostream> namespace Visitor { struct ShapeVisitor; class Rectangle; class Circle; /*********************************************************************************/ // code added for triangle class Triangle; /*********************************************************************************/ struct Shape { virtual void Draw()=0; virtual void Move()=0; virtual void Accept(ShapeVisitor*)=0; virtual ~Shape()=0{}; }; struct ShapeVisitor { virtual void Visit(Rectangle*)=0; virtual void Visit(Circle*)=0; /*********************************************************************************/ // code added for triangle virtual void Visit(Triangle*)=0; /*********************************************************************************/ virtual ~ShapeVisitor()=0{}; }; class Rectangle:public Shape { public: virtual void Draw() { std::cerr<<"Rectangle Draw"<<std::endl; } virtual void Move() { std::cerr<<"Rectangle Move"<<std::endl; } virtual void Accept(ShapeVisitor* visitor) { visitor->Visit(this); } }; class Circle:public Shape { public: virtual void Draw() { std::cerr<<"Circle Draw"<<std::endl; } virtual void Move() { std::cerr<<"Circle Move"<<std::endl; } virtual void Accept(ShapeVisitor* visitor) { visitor->Visit(this); } }; /*********************************************************************************/ // code added for triangle class Triangle:public Shape { public: virtual void Draw() { std::cerr<<"Triangle Draw"<<std::endl; } virtual void Move() { std::cerr<<"Triangle Move"<<std::endl; } virtual void Accept(ShapeVisitor* visitor) { visitor->Visit(this); } }; /*********************************************************************************/ } #endif //__A0CC449E0FC0993D677D76384ECE93051C2525CA76E1FAE__
VisitorTest.cpp
代码:
#include "Visitor.h" #include <iostream> namespace Visitor { class MyVisitor:public ShapeVisitor { public: virtual void Visit(Rectangle* r) { r->Move(); r->Draw(); } virtual void Visit(Circle* c) { c->Move(); c->Draw(); } /*********************************************************************************/ // code added for triangle virtual void Visit(Triangle* t) { t->Move(); t->Draw(); } /*********************************************************************************/ }; void test() { Rectangle rect; Circle circle; MyVisitor visitor; rect.Accept(&visitor); circle.Accept(&visitor); /*********************************************************************************/ // code added for triangle Triangle triangle; triangle.Accept(&visitor); /*********************************************************************************/ } } int main(int argc, char* argv[]) { std::cerr<<"------------------------------------------------------------\nTesting Visitor"<<std::endl; Visitor::test(); return 0; }
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #2 (permalink)  
旧 2002-09-13
普通会员
 
注册日期: 2002-09-10
住址: 湖北襄樊
帖子: 77
口天草芳 正向着好的方向发展
默认

天呀,真不知我以前学的是什么,这些内容我从未接触过。我这的书里没有讲这些内容,你们都是从哪学来的呀。写点基础的文章给我补补课吧!看来我要去买本内容强的书看看了。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #3 (permalink)  
旧 2002-09-13
polyrandom 的头像
超级版主
 
注册日期: 2002-09-03
帖子: 3,138
文章: 20
polyrandom 正向着好的方向发展
默认

据我所知,visitor在有些书上出现了,但是acyclic visitor没有在任何一本书上出现过。
而且你也不要觉得灰心,我学C++8年了,到这里还是学到很多东西,所以我也希望abp能够多写一些文章。
你要学很简单,只要做两件事情:多写程序,多来这里讨论。后者可以让你学到东西,前者可以让你知道学到的东西有什么用。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #4 (permalink)  
旧 2002-09-25
普通会员
 
注册日期: 2002-09-19
住址: 中国
帖子: 87
飚风极速 正向着好的方向发展
默认

看了这PORA兄这段话我倒大增信心了。因为我C++才学2个月不到(C也才学了大半年)
我要大补C++和C
PORA,BP兄,有没有最好的C++中文版的书???
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #5 (permalink)  
旧 2002-09-26
abp 的头像
abp abp 当前离线
高级会员
 
注册日期: 2002-08-30
帖子: 811
abp 正向着好的方向发展
默认

没有最好的书的,只有最合适的书。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #6 (permalink)  
旧 2002-10-11
lonelywhisper 的头像
高级会员
 
注册日期: 2002-09-25
帖子: 111
lonelywhisper 正向着好的方向发展
发送 MSN 消息给 lonelywhisper
默认

越贵越好, pora兄,你说是吧?
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #7 (permalink)  
旧 2002-10-11
polyrandom 的头像
超级版主
 
注册日期: 2002-09-03
帖子: 3,138
文章: 20
polyrandom 正向着好的方向发展
默认

的确,我觉得书不在多,有几本好的就行了。所以我挑贵的买。
我这个月又买了2000多的书,55555555
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #8 (permalink)  
旧 2002-10-11
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

好有钱啦,口水ing

借我看两本吧,比如modern c++ design,买书不如借书,
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #9 (permalink)  
旧 2002-10-11
polyrandom 的头像
超级版主
 
注册日期: 2002-09-03
帖子: 3,138
文章: 20
polyrandom 正向着好的方向发展
默认

你为什么认为我有modern c++ design?
不过我不喜欢翻译的书和影印版,我喜欢原版。
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
  #10 (permalink)  
旧 2002-10-11
高级会员
 
注册日期: 2002-09-16
帖子: 1,087
文章: 1
SpitFire 正向着好的方向发展
默认

hehe,因为我知道你有,才说modern c++ design这本书的啊

看来你家里的好书不少,要多掏掏
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
回复时引用此帖
回复

书签

主题工具
显示模式

发帖规则
不可以发表新主题
不可以发表回复
不可以上传附件
不可以编辑自己的帖子

启用 BB 代码
论坛启用 表情符号
论坛启用 [IMG] 代码
论坛禁用 HTML 代码
Trackbacks are 启用
Pingbacks are 启用
Refbacks are 启用


相似的主题
主题 主题作者 版面 回复 最后发表
[讨论]私有成员:直接引出还是添加操作函数? pomb 技术杂烩 7 2004-07-22 07:01 PM
functional的pattern match vs. OO的visitor vs. if/switch ajoo 技术杂烩 49 2003-09-22 04:51 PM
cg扩展之二:协议名字做参数 (以及在type list中的应用) ajoo 技术杂烩 5 2003-08-19 09:47 AM
怎样解决这个问题?关于point类体系的打印问题。 abp C/CPP/TMP/GP 23 2002-10-11 03:01 PM
Acyclic Visitor / RTTI Visitor abp 技术杂烩 26 2002-09-20 02:58 PM


所有时间均为格林尼治时间 +9。现在的时间是 09:41 AM


Powered by vBulletin® 版本 3.7.0
版权所有 ©2000 - 2009,Jelsoft Enterprises Ltd.
(C) Copy Right All Right Reserved 2001 - 2007

Search Engine Friendly URLs by vBSEO 3.1.0