科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件visitor模式概念——visitor模式进一步

visitor模式概念——visitor模式进一步

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

一,访问者模式的角色:抽象访问者:声明一个或者多个访问操作,形成所有的具体元素都要实现的接口具体访问者:实现抽象访问者所声明的接口

作者:中国IT实验室 来源:中国IT实验室 2007年8月26日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
这样只要调用run方法,传入对应的参数就能执行了。
还有一个问题就是判断类型。由于重载(overloading)是静态多分配(java语言本身是支持"静态多分配"的。
关于这个概念请看这里)所以造成重载只根据传入对象的定义类型,而不是实际的类型,所以必须在传入前就确定类型,
这可是个难的问题,因为在容器中对象全是Object,出来后要是判断是什么类型必须用
if (xx instanceof xxx)这种方法,如果用这种方法启不是又回到了原点,有没有什么更好的办法呢?

我们知到Java还有另外一个特点,覆写(overriding),而覆写是"动态单分配"的(关于这个概念见这里),
那如何利用这个来实现呢?看下边这个方法:
 我们让上边的一些类PA PB PC PD PE都实现一个接口P,加入一个方法,accept();


 1   public   void  accept(visitor v)  {
 2      // 把自己传入1 
 3      v.run( this );
 4 } 
 5 然後在visitor中加入一个方法
 6   public   void  run(P p)  {
 7      // 把自己传入2 
 8      p.accept( this );
 9 } 
10  // 这样你在遍历中可以这样写 
11  Visitor v  =   new  Visitor();
12 Iterator ie  =  list.iterator();
13   while (ie.hasNext())  {
14     P p  =  (P)ie.next();
15         p.accept(v);
16     } 
17 } 

首先执行的是"把自己传入2",在这里由于Java的特性,实际执行的是子类的accept(),也就是实际类的accept
然後是"把自己传入1",在这里再次把this传入,就明确类型,ok我们巧妙的利用overriding解决了这个问题
其实归纳一下第二部分,一个关键点是"自己认识自己",是不是很可笑。
其实在计算计技术领域的很多技术上看起来很高深的东西,其实就是现有社会中人的生活方式的一种映射
而且这种方式是简单的不能再简单的方式。上边的全部过程基本上是一个简单的visitor模式实现,visitor模式
已经是设计模式中比较复杂的模式了,但其实原理简单到你想笑。看看下边这个比喻也许你的理解会更深刻。

四:一个帮助理解的比喻:
题目:指挥工人工作
条件:你有10个全能工人,10样相同工作。
需求:做完工作
实现:大喊一声所有人去工作

条件变了,工人不是全能,但是工作相同,ok问题不大
条件再变,工作不是相同,但工人是全能,ok问题不大

以上三种情况在现实生活中是很少发生得,最多的情况是这样:
10个工人,每人会做一种工作,10样工作。你又一份名单Collection)写着谁做什么。但你不认识任何人
这个时候你怎么指挥呢,方案一:
你可以一个个的叫工人,然後问他们名字,认识他们,查名单,告诉他们做什么工作。
你可以直接叫出他们名字,告诉他们干什么,不需要知到他是谁。
看起来很简单。但如果你要指挥10万人呢 ?而且人员是流动的,每天的人不同,你每天拿到一张文档。
其实很简单,最常用的做法是,你把这份名单贴在墙上,然後大喊一声,所有人按照去看,按照自己的分配情况去做。
这里利用的关键点是"所有工人自己认识自己",你不能苛求每个工人会做所有工作,不能苛求所有工作相同,但你
能要求所有工人都认识自己。

再想想我们开始的程序,每个工人对应着PA PB PC PD PE....
所有的工人都使工人P
每个工人会做的东西不一样runPA runPB runPC
你有一份名单Visitor(重载)记录着谁做什么工作。

看完上边这些,你是不是会产生如下的问题:
问题:为什么不把这些方法的方法名做成一样的,那就可以解决了。
例如,我们每个PA ,PB ,PC都加入一个run 方法,然後run内部再调用自己对应的runPx()方法。
答案:有些时候从不同的角度考虑,或者因为实现的复杂度早成很难统一方法名。
例如上边指挥人工作的例子的例子,其实run方法就是大叫一声去工作,因为每个工人只会做一种工作,所以能行
但我们不能要求所有人只能会做一种事情,这个要求很愚蠢。所以如果每个工人会干两种或者多种工作呢,
也就是我PA 有runPA() walkPA()等等方法, PB有runPB() climbPB()等等。。。
这个时候按照名单做事才是最好的办法。
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章