ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

设计模式--访问者模式

2021-07-06 15:59:35  阅读:163  来源: 互联网

标签:-- visitor Bean accept IVisitor bean 设计模式 访问者


Visitor Pattern

网抄访问者模式概念

在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。

在这里插入图片描述

看这个图实在是一言难尽啊,我们从另外一个角度来简析这个模式吧。 咱们首先看看被访问者吧。从这个角色来理解。

假设我们有一个非常非常普通的数据。如下!

在这里插入图片描述

如果想让别人访问的话,其实相当好说,就是bean.getxxx(), 就得了是吧。 如果这样简单,根本就出现不了访问者了。

假设,我有个需求,让你花式打印这几种英雄的信息嘞。 这也就意味着,你面对每一个”花式“都得写一种算法。例如吧: 我想让你用英语,汉语,繁体,韩语,日语各自打印一些bean的自我介绍。

第一个反映估计是:

if (汉语) {
    拿bean篡汉语
} else if (韩语) {
    拿bean篡韩语
}.....

也行是吧。但是不优雅。

模式初步

bean还是bean, 将转化为各种语言,算作不同的算法。 让这些算法能访问到这个bean,拿到bean,各自篡各自的文案。

在这些最普通的bean上,估计要加一些额外的方法,起码要有一个访问接口。但是接口不建议过多。网上通常一个接口,叫accept。 那么问题来了, 就提供一个接口的话,你怎么知道人家想捞什么数据呢?全部都给的话会很尴尬,不全部给的话,你又不知道给啥。所以要怎么搞呢?我们根据平常的场景,我们设定了被访问者,有没有发现,目前还没有访问者什么事呢。访问学那么答案来了,我们可以把这个访问者用上。外部向这些bean要数据的时候,不会直接用这些bean 去get,而是用这些访问者,去访问bean的数据结构中的每个元素。 写到这里,你是不是感觉,这个访问者最为直接访问真实数据的角色,是不是可以利用它来,对数据做一些”添油加醋“的操作,而不会导致原始的数据有改变呢? 哈哈哈,层多了,留的空子就越多,当然可以喽。

对于被访问者
接收一个访问者,把自己的引用传给它,至于它拿到你自身的引用,去做什么,生成什么结果。这个你根本不用管。毕竟包揽的太多了不好。还不如搞一个比较通用的。而作为被访问者,你做好的事情,就是,管好自己的成员变量,不要老被别人改来改去。做好约束,比如把修改的权限收回,把读取的权限放开。定制好了规则,后来人写代码,只能在你指定的包内搞,并不会因此坏了结构。

IBean{
    accept(IVisitor visitor);
}

对于访问者
Visitor作为一个访问者,并且一般是由客户端代码直接或者间接调用的,说白了,他可能具有较强的业务性,场景性。里面的接口,或许也是和业务相关的。所以嘞,这个访问者在此时,直接写一个基类接口, IVisitor, 可变性太大,具体也不知道写啥呀。先把规则定了再说。
但是总有一个方法得用来调用一下吧。我们暂时随便给一个方法把,否则例子要无法延伸了!

IVisitor {
    String getImportantInfo(Bean bean);
}

简单实现

Bean {
    void accept(IVisitor visitor) {
        visitor.getImportantInfo(this);
    }
}

这句代码,总结一句话,就是,Bean作为一个被访问者,接受一个访问者,实现的时候,把自身的句柄传给访问者,怎么传,就是调用一个访问者的方法,然后将自己的句柄作为参数喽。这个是访问者模式的核心。我把他当成核心。至于外部的花式调用啥的,都是浮云。


那么这样的话,我们就需要再加点角色了,就是访问者角色。 然后再在这些bean里加一些能接受这些访问者的角色,把自己传出去,bean的职责已尽,该给的都给出去了,至于外部究竟能拿这个访问者访问自己,最终得到的是什么个结果,都已与自己无关。

类图进化:
在这里插入图片描述


外界怎么调用呢?

private Bean mBean = new xxxxx();
private Bean mBean2 = new nnnnn();
private IVisitor mVisitor = new xxxVisitor();
private IVisitor mVisitor2 = new cccVisitor();

main(..., ...) {
    // 重点, bean.accept()有没有发现,最开始也是bean句柄调用的。
    // 但是accept的访问者,是可以变化的,结果是根据这个访问者不同,从而打印的不同!
    mBean.accept(mVisitor);
    mBean2.accept(mVisitor);

    // 看吧,bean统一调用accept方法, 但是具体干了啥,完全仰仗IVisitor的实现具体干了啥。
    mBean.accept(mVisitor2);
    mBean2.accept(mVisitor2);
}

visitor如何实现

Visitor {
    String getImportantInfo(Bean bean) {
        // 汉语打印英雄
    }
}

拓展

Visitor如果真的像这样实现,基本完全不能发挥其能力,上面已经讲过,Ivisitor是和业务相关的,很容易变化的。而且基本描述的是,拿到一套数据后的算法。比如我可不可以这样衍生?
在这里插入图片描述

或者我不衍生了!直接在visitor中加方法。 这个是网上通常看到的案例。我觉得这个使用起来不太优雅。反正我不会这么用。

在这里插入图片描述

标签:--,visitor,Bean,accept,IVisitor,bean,设计模式,访问者
来源: https://blog.csdn.net/weixin_28774815/article/details/118522307

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有