大话设计模式笔记(二十五)の访问者模式

访问者模式

定义

表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

UML图

特点

  • 访问者模式适用于数据结构相对稳定的系统,它把数据和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化
  • 访问者模式的目的是要把处理从数据结构分离出来
  • 如果有比较稳定的数据结构,又易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易
  • 访问者模式的优点就是增加新的操作很容易,因为增加新的操作就意味着增加一个新的访问者。访问者模式将有关的行为集中到一个访问者对象中
  • 访问者的缺点其实也就是使增加新的数据结构变得困难。

举个栗子

人,分为男人和女人,分别描述他/她成功、失败、恋爱时的不同原因。。。

UML图

Talk is cheap, show me the code

(屁话少说,放码过来)

 1.  /**
 2.   * 状态
 3.   * Created by callmeDevil on 2019/12/22.
 4.   */
 5.  public abstract class Action {
 6.      // 得到男人结论或反应
 7.      public abstract void getManConclusion(Man concreteElementA);
 8.      // 得到女人结论或反应
 9.      public abstract void getWomanConclusion(Woman concreteElementB);
10.  }
11.  
 1.  /**
 2.   * 成功
 3.   * Created by callmeDevil on 2019/12/22.
 4.   */
 5.  public class Success extends Action {
 6.  
 7.      @Override
 8.      public void getManConclusion(Man concreteElementA) {
 9.          System.out.println(String.format("%s %s时,背后多半有一个伟大的女人。",
10.                  concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
11.      }
12.  
13.      @Override
14.      public void getWomanConclusion(Woman concreteElementB) {
15.          System.out.println(String.format("%s %s时,背后多半有一个不成功的男人。",
16.                  concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
17.      }
18.  
19.  }
20.  
 1.  /**
 2.   * 失败
 3.   * Created by callmeDevil on 2019/12/22.
 4.   */
 5.  public class Failing extends Action {
 6.  
 7.      @Override
 8.      public void getManConclusion(Man concreteElementA) {
 9.          System.out.println(String.format("%s %s时,背后多半有一个不伟大的女人。",
10.                  concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
11.      }
12.  
13.      @Override
14.      public void getWomanConclusion(Woman concreteElementB) {
15.          System.out.println(String.format("%s %s时,背后多半有一个成功的男人。",
16.                  concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
17.      }
18.  
19.  }
20.  
 1.  /**
 2.   * 恋爱
 3.   * Created by callmeDevil on 2019/12/22.
 4.   */
 5.  public class Amativeness extends Action {
 6.  
 7.      @Override
 8.      public void getManConclusion(Man concreteElementA) {
 9.          System.out.println(String.format("%s %s时,背后多半是个高富帅。",
10.                  concreteElementA.getClass().getSimpleName(), this.getClass().getSimpleName()));
11.      }
12.  
13.      @Override
14.      public void getWomanConclusion(Woman concreteElementB) {
15.          System.out.println(String.format("%s %s时,背后多半是个会打扮。",
16.                  concreteElementB.getClass().getSimpleName(), this.getClass().getSimpleName()));
17.      }
18.  
19.  }
20.  
1.  /**
2.   * 人
3.   * Created by callmeDevil on 2019/12/22.
4.   */
5.  public abstract class Person {
6.      // 接受
7.      public abstract void accept(Action visitor);
8.  }
9.  
 1.  /**
 2.   * 男人
 3.   * Created by callmeDevil on 2019/12/22.
 4.   */
 5.  public class Man extends Person{
 6.      @Override
 7.      public void accept(Action visitor) {
 8.          // 首先在客户端程序中将具体状态作为参数传递给“男人”类完成了一次分派,然后“男人”类调用
 9.          // 作为参数的“具体状态”中的方法“男人反应”,同时将自己(this)作为参数传递进去,这便完成
10.          // 了第二次分派。这种技术手段称为“双分派”。
11.          visitor.getManConclusion(this);
12.      }
13.  }
14.  
 1.  /**
 2.   * 女人
 3.   * Created by callmeDevil on 2019/12/22.
 4.   */
 5.  public class Woman extends Person{
 6.      @Override
 7.      public void accept(Action visitor) {
 8.          visitor.getWomanConclusion(this);
 9.      }
10.  }
11.  
 1.  /**
 2.   * 对象结构
 3.   * Created by callmeDevil on 2019/12/22.
 4.   */
 5.  public class ObjectStructure {
 6.  
 7.      private List<Person> elements = new ArrayList<>();
 8.  
 9.      // 增加
10.      public void attach(Person element) {
11.          elements.add(element);
12.      }
13.  
14.      // 移除
15.      public void detach(Person element) {
16.          elements.remove(element);
17.      }
18.  
19.      // 查看显示
20.      public void display(Action visitor) {
21.          for (Person element : elements) {
22.              element.accept(visitor);
23.          }
24.      }
25.  
26.  }
27.  
 1.  public class Test {
 2.      public static void main(String[] args) {
 3.          ObjectStructure obj = new ObjectStructure();
 4.          // 对象结构中加入要对比的男人和女人
 5.          obj.attach(new Man());
 6.          obj.attach(new Woman());
 7.  
 8.          // 成功的反应
 9.          Success success = new Success();
10.          obj.display(success);
11.  
12.          // 失败的反应
13.          Failing failing = new Failing();
14.          obj.display(failing);
15.  
16.          // 恋爱的反应
17.          Amativeness amativeness = new Amativeness();
18.          obj.display(amativeness);
19.      }
20.  }
21.  

运行结果

1.  Man Success时,背后多半有一个伟大的女人。
2.  Woman Success时,背后多半有一个不成功的男人。
3.  Man Failing时,背后多半有一个不伟大的女人。
4.  Woman Failing时,背后多半有一个成功的男人。
5.  Man Amativeness时,背后多半是个高富帅。
6.  Woman Amativeness时,背后多半是个会打扮。
7.  
posted @   callmeDevil  阅读(408)  评论(0编辑  收藏  举报
编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥
点击右上角即可分享
微信分享提示