行为型模式[访问者模式]

访问者模式是一种将数据结构与数据操作分离的设计模式。是指封装一些作用于某些数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。属于行为型模式。

访问者模式被称为最复杂的设计模式,并且使用频率不高,设计模式的作者也评论为:大多数情况下,你不需要使用访问者模式,但是一旦需要使用它时,那就是真的需要使用了。访问者模式的基本思想时,针对系统中拥有固定类型数的对象结构(元素),在其内提供一个accept()方法用来接受访问者对象的访问。不同的访问者对同一元素的访问内容不同,使得相同的元素集合可以产生不同的数据结果。accept()方法可以接收不同的访问者对象,然后在内部将自己(元素)转发到接收到的访问者对象的visit()方法内。访问者内部对应类型的visit()方法就会得到回调执行,对元素进行操作。也就是通过两次动态转发(第一次是对访问者的分发accept()方法,第二次是对元素的分发visit()方法),才最终将一个具体的元素传递到一个具体的访问者。如此一来,就解耦了数据结构与操作,且数据操作不会改变元素状态。

访问者模式的核心是,解耦数据结构与数据操作,使得对元素的操作具备优秀的扩展性。可以通过扩展不同的数据操作类型(访问者)实现对相同元素集的不同的操作。

访问者模式的应用场景
1、数据结构稳定,作用于数据结构的操作经常变化的场景。
2、需要数据结构与数据操作分离的场景。
3、需要对不同数据类型(元素)进行操作,而不使用分支判断具体类型的场景。

访问者模式通用UML类图:

1、抽象访问者(visit):接口或者抽象类,该类对应了每一个具体元素(Hero子类)的访问行为visit()方法,其参数就是具体的元素(Hero)对象。理论上来说,visit的方法个数与元素(Hero子类)个数是相等的。如果元素
(Hero)个数变动会导致visit的方法也要进行变动,此时,该情形并不适用访问者模式。
2、具体访问者(Player子类):实现对具体元素的操作。
3、抽象元素(Hero):接口或抽象类,定义了一个接受访问者访问的方法accept(),表示所有元素类型都支持被访问者访问。
4、具体元素(Hero子类):具体元素类型,提供接受访问者的具体实现。
5、结构对象(ObjectStruture):该类内部维护了元素集合,并提供方法接受访问者对该集合所有元素进行操作。

// 抽象元素
public interface Hero { // 英雄void accept(Player player);}
// 具体元素
public class DaYeHero implements Hero{// 打野英雄private String name;private int score;public DaYeHero(String name) {this.name = name;this.score = score();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}public void accept(Player player) {player.visit(this);}public int score() {return new Random().nextInt(100);}
}
public class FuZhuHero implements Hero {// 辅助英雄private String name;private int score;public FuZhuHero(String name) {this.name = name;this.score = score();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}public void accept(Player player) {player.visit(this);}public int score() {return new Random().nextInt(100);}
}
public class ShangDanHero implements Hero {// 上单英雄private String name;private int score;public ShangDanHero(String name) {this.name = name;this.score = score();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}public void accept(Player player) {player.visit(this);}public int score() {return new Random().nextInt(100);}
}
public class SheShouHero implements Hero {// 射手英雄private String name;private int score;public SheShouHero(String name) {this.name = name;this.score = score();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}public void accept(Player player) {player.visit(this);}public int score() {return new Random().nextInt(100);}
}
public class ZhongDanHero implements Hero{// 中单英雄private String name;private int score;public ZhongDanHero(String name) {this.name = name;this.score = score();}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}public void accept(Player player) {player.visit(this);}public int score() {return new Random().nextInt(100);}
}
// 抽象访问者(visit)
public interface Player {   // 玩家void visit(DaYeHero daYeHero);void visit(FuZhuHero fuZhuHero);void visit(ShangDanHero shangDanHero);void visit(SheShouHero sheShouHero);void visit(ZhongDanHero zhongDanHero);
}
// 具体访问者
public class DaYePlayer implements Player{  // 打野玩家public void visit(DaYeHero daYeHero) {System.out.println("没有打野他们啥都不是,打野无敌,给"+daYeHero.getName()+"这个英雄打个"+(daYeHero.score()*0.5));}public void visit(FuZhuHero fuZhuHero) {System.out.println("辅助这个位置就是大混子,给"+fuZhuHero.getName()+"这个英雄打个"+(fuZhuHero.score()*0.2));}public void visit(ShangDanHero shangDanHero) {System.out.println("上单这个位置混子,给"+shangDanHero.getName()+"这个英雄打个"+(shangDanHero.score()*0.6));}public void visit(SheShouHero sheShouHero) {System.out.println("射手这个位置混子,给"+sheShouHero.getName()+"这个英雄打个"+(sheShouHero.score()*0.1));}public void visit(ZhongDanHero zhongDanHero) {System.out.println("中单菜就算了还不给我吃线,混子,给"+zhongDanHero.getName()+"这个英雄打个"+(zhongDanHero.score()));}
}
public class FuZhuPlayer implements Player{ //辅助玩家public void visit(DaYeHero daYeHero) {System.out.println("打野马仔,给"+daYeHero.getName()+"这个英雄打个"+(daYeHero.score()*0.2));}public void visit(FuZhuHero fuZhuHero) {System.out.println("辅助是baba,给"+fuZhuHero.getName()+"这个英雄打个"+(fuZhuHero.score()*1.1));}public void visit(ShangDanHero shangDanHero) {System.out.println("上单废物,给"+shangDanHero.getName()+"这个英雄打个"+(shangDanHero.score()*0.2));}public void visit(SheShouHero sheShouHero) {System.out.println("射手erzi,给"+sheShouHero.getName()+"这个英雄打个"+(sheShouHero.score()*0.3));}public void visit(ZhongDanHero zhongDanHero) {System.out.println("中单废物,给"+zhongDanHero.getName()+"这个英雄打个"+(zhongDanHero.score()*2));}
}
public class ZhongDanPlayer implements Player{  // 中单玩家public void visit(DaYeHero daYeHero) {System.out.println("打野这个位置嘛,就会吃我中路线啥用都没有,给"+daYeHero.getName()+"这个英雄打个"+(daYeHero.score()*0.5));}public void visit(FuZhuHero fuZhuHero) {System.out.println("辅助这个位置就是大混子,给"+fuZhuHero.getName()+"这个英雄打个"+(fuZhuHero.score()*0.2));}public void visit(ShangDanHero shangDanHero) {System.out.println("上单这个位置也不会支援人,就知道在上路呆着,给"+shangDanHero.getName()+"这个英雄打个"+(shangDanHero.score()*0.6));}public void visit(SheShouHero sheShouHero) {System.out.println("射手这个位置不用说就只会补兵啥事不会,给"+sheShouHero.getName()+"这个英雄打个"+(sheShouHero.score()*0.1));}public void visit(ZhongDanHero zhongDanHero) {System.out.println("中单无敌误解,给"+zhongDanHero.getName()+"这个英雄打个"+(zhongDanHero.score()));}
}
// 结构对象
public class ObjectStructure {private List<Hero> list = new ArrayList<Hero>();{this.list.add(new DaYeHero("娜可露露"));this.list.add(new FuZhuHero("牛魔"));this.list.add(new ZhongDanHero("高渐离"));this.list.add(new DaYeHero("赵云"));this.list.add(new FuZhuHero("大乔"));this.list.add(new FuZhuHero("太乙真人"));this.list.add(new ShangDanHero("马超"));this.list.add(new SheShouHero("艾琳"));this.list.add(new ShangDanHero("关羽"));this.list.add(new SheShouHero("公孙离"));this.list.add(new ZhongDanHero("杨玉环"));this.list.add(new SheShouHero("李元芳"));}public void accept(Player player) {for (Hero hero : this.list) {hero.accept(player);System.out.println();}}
}public class Test {public static void main(String[] args) {ObjectStructure objectStructure = new ObjectStructure();System.out.println("===============打野评论=================");objectStructure.accept(new DaYePlayer());System.out.println("===============中单评论=================");objectStructure.accept(new ZhongDanPlayer());System.out.println("===============辅助评论=================");objectStructure.accept(new FuZhuPlayer());}
}

访问者模式优缺点

优点:
1、解耦了数据结构与数据操作,使得操作集合可以独立变化。
2、扩展性好:可以通过扩展访问者角色,实现对数据集得不同操作。
3、元素具体类型并非单一,访问者均可操作.
4、各角色职责分离,符合单一职责原则。

缺点:
1、无法添加元素类型:诺系统数据结构对象易于变化,经常有新的数据对象添加进来,则访问者类必须添加对应元素类型的操作,违背了开闭原则。
2、具体元素变更困难:具体元素添加属性,删除属性等操作会导致对应的访问者类需要进行相应的修改,尤其当大量访问者类时,修改范围太大。
3、违背依赖倒置原则:为了达到【区别对待】,访问者依赖的时具体元素类型,而不是抽象。

行为型模式【访问者模式】相关推荐

  1. Java设计模式之行为型:访问者模式

    背景: 去医院看病时,医生会给你一个处方单要你去拿药,拿药我们可以分为两步走: (1)去柜台交钱,划价人员会根据处方单上的药进行划价,交钱. (2)去药房拿药,药房工作者同样根据处方单给你相对应的药. ...

  2. OOP 中的 方法调用、接口、鸭式辩型、访问者模式

    2019独角兽企业重金招聘Python工程师标准>>> 方法调用的四种方式 直接调用:通过类或者实例直接调用其方法. 接口调用或者转型调用:通过将实例回调给一个接口对象,或者转型为一 ...

  3. 【Java设计模式】:行为型模式—访问者模式

    1. 访问者模式简介 访问者模式,是行为型设计模式之一.访问者模式是一种将数据操作与数据结构分离的设计模式,它可以算是 23 中设计模式中最复杂的一个,但它的使用频率并不是很高,大多数情况下,你并不需 ...

  4. 23种设计模式-行为型模式-访问者模式

    在患者就医时,医生会根据病情开具处方单,很多医院都会存在以下这个流程:划价人员拿到处方单之后根据药品名称和数量计算总价,而药房工作人员根据药品名称和数量准备药品,如下图所示. 在软件开发中,有时候也需 ...

  5. 设计模式 — 行为型模式 — 访问者模式

    目录 文章目录 目录 访问者模式(Visitor Pattern) 应用场景 代码示例 访问者模式(Visitor Pattern) 数据结构中保存着许多元素,当我们希望改变一种对元素的处理方式时,要 ...

  6. yii2通过url访问类中的方法_行为型设计模式 访问者模式

    author zong email zongzhe1996@163.com 介绍 在访问者模式中,通过使用一个访问者类,可以改变元素类(被访问者)的执行算法.元素类的执行算法可以随着访问者的改变而改变 ...

  7. 23种设计模式的JAVA实现——访问者模式(行为型模式)

    访问者模式 访问者模式:在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法.通过这种方式,元素的执行算法可以随着访问者改变而改变.这种类型的设计模式属于 ...

  8. 设计模式之美——行为型3:迭代模式、访问者模式、命令模式、解释器模式、中介模式

    迭代器模式 迭代器模式的原理和实现 迭代器模式(Iterator Design Pattern),也叫作游标模式(Cursor Design Pattern). 迭代器模式.它用来遍历集合对象.这里说 ...

  9. 【设计模式】访问者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 一.访问者模式简介 二.访问者模式 适用场景 三.访问者模式 优缺点 四.访问者模式 与 迭代器模式 五.代码示例 1.Game 父类 ( 被访问者 ) 2.VipGame 收费游戏 ( 被 ...

最新文章

  1. 近期活动盘点:俞士纶见面会、2018未来医疗100强论坛、清华校友三创论坛、2018年中国数字政府论坛(12.18-12.21)...
  2. HTML5 geolocation和BaiduMap、BingMap、GoogleMap
  3. final关键字用法
  4. ssh“权限太开放”错误
  5. 从零学习 vim 一个多月, 感觉最有用的三个教程
  6. C++中三种正则表达式比较(C regex,C ++regex,boost regex)
  7. 参加ISCC2019线下赛感悟
  8. 安卓进阶系列-04自定义原型图片显示(CircleImageView)的使用
  9. js生日计算年龄_你知道用EXCEL可以从身份证中提取生日、性别、年龄、生肖吗?...
  10. 特征缩放的效果:从词袋到 TF-IDF
  11. 【报告分享】管理者实效管理工具包:用最佳策略和资源留住您最优秀的人才.pdf...
  12. 响应头中content-type常用的类型有哪些?
  13. Java 接口和抽象类的异同点
  14. 一步一步学Repast 第五章——模拟粒子运动,了解Schedule
  15. 世界尽头与冷酷仙境(村上春树)-摘录
  16. Office安装时遇到的问题
  17. 「兔了个兔」福兔贺春,纯CSS实现超精美月兔404界面(附源码)
  18. JIS-CTF解题思路及关键语句
  19. 西安交通大学计算机学院保研面试,西安交通大学电子与信息工程学院(专业学位)计算机技术保研细则...
  20. 支持win7的node.js版本+node和npm版本不匹配问题解决

热门文章

  1. C语言——格式控制字符%m.nf和%-m.nf练习.c++002
  2. 计算机二级报名支付了两次,计算机二级报名步骤
  3. Matplotlib赋予Python数据一双眼
  4. Java并发_3 ThreadLocal
  5. bentoml部署深度学习模型(一)
  6. Android系统读取 CPU温度(MTK平台)
  7. 程序员标配--使用hexo+github搭建个人博客
  8. 智能家居——火灾报警设计
  9. ARP协议以及RARP协议的工作原理
  10. Mina IoBuffer的特性介绍