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

访问者模式

  • 1.访问者模式解决的问题
  • 2.访问者模式中的角色
  • 3.关系
  • 4.例子
    • 4.1结构图
    • 4.2 抽象数据结构
    • 4.3 实际的数据结构
    • 4.4 抽象的访问者
    • 4.5 实际的访问者
    • 4.6 访问者数据分配
    • 4.7 结果
    • 4.8 增加一个访问者
    • 4.9 访问者分配者
    • 4.10 结果
  • 5.知识点
    • 5.1 双重分发
    • 5.2 数据与处理分离
    • 5.3 开闭原则
    • 5.4 扩展

23种设计模式

1.访问者模式解决的问题

首先看这样的一个情景:
西游记师徒四人,一路十万八千里。每日都需要化缘才能有吃的。
大师兄本领强大,直接去找吃的,不给就硬抢。
猪八戒好吃懒作,会去偷吃的。
沙和尚为人老实,会用自己的力气化缘。
至于唐僧则是给人讲佛法,以此来化缘。

所以,我们可以发现:对于同一件事情,或者说同一个事物,师徒四人用自己独特的方式达到目的。

对于食物,就是访问者模式中基本的数据,但是处理这个数据有着许多的方式,为了将数据与操作分离,或者为了更加方便的增加访问数据的方式,访问者模式能够很好的解决这一问题。

2.访问者模式中的角色

抽象的数据accept
具体的数据accept
抽象的访问者visit
具体的访问者visit
访问者数据分配

3.关系

实现
实现
实现
关联 Visitor AbsVisit ImplEle1 AbsEle ImplEle2 Structure

4.例子

仿照化缘的过程,我们做一个简单的例子。

4.1结构图

《23种设计模式----访问者模式----行为型模式》

4.2 抽象数据结构

package visitor.element.abs;

import visitor.visit.abs.Visit;

public abstract class Home {

   private String name;
   
   public abstract void accept(Visit visit);
   
   public Home(String name){
   	this.name = name;
   }

   public String getName() {
   	return name;
   }

   public void setName(String name) {
   	this.name = name;
   }
   
}

4.3 实际的数据结构

package visitor.element.impl;

import visitor.element.abs.Home;
import visitor.visit.abs.Visit;

public class Home1 extends Home{

   public Home1(String name) {
   	super(name);
   }

   @Override
   public void accept(Visit visit) {
   	System.out.println("accept#home1");
   	visit.visit(this);
   }

}

package visitor.element.impl;

import visitor.element.abs.Home;
import visitor.visit.abs.Visit;

public class Home2 extends Home{

   public Home2(String name) {
   	super(name);
   }

   @Override
   public void accept(Visit visit) {
   	System.out.println("accept#home2");
   	visit.visit(this);
   }

}

4.4 抽象的访问者

package visitor.visit.abs;

import visitor.element.impl.Home1;
import visitor.element.impl.Home2;

public interface Visit {

   public void visit(Home1 home1);
   
   public void visit(Home2 home2);
   
}

4.5 实际的访问者

package visitor.visit.impl;

import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.abs.Visit;

public class Visitor implements Visit{

   @Override
   public void visit(Home1 home1) {
   	System.out.println("visit#home1");
   	
   }

   @Override
   public void visit(Home2 home2) {
   	System.out.println("visit#home2");
   }

}

package visitor.visit.impl;

import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.abs.Visit;

public class Visitor1 implements Visit{

   @Override
   public void visit(Home1 home1) {
   	System.out.println("visit&home1");
   }

   @Override
   public void visit(Home2 home2) {
   	System.out.println("visit&home2");
   }

}

4.6 访问者数据分配

package visitor.client;

import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.impl.Visitor;
import visitor.visit.impl.Visitor1;

public class Main {

   public static void main(String[] args) {
   	new Home1("home1").accept(new Visitor());
   	new Home2("home2").accept(new Visitor());
   	
   	new Home1("home1").accept(new Visitor1());
   	new Home2("home2").accept(new Visitor1());
   }

}

4.7 结果

accept#home1
visit#home1
accept#home2
visit#home2
accept#home1
visit&home1
accept#home2
visit&home2

4.8 增加一个访问者

package visitor.visit.impl;

import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.abs.Visit;

public class Visitor2 implements Visit{

   @Override
   public void visit(Home1 home1) {
   	System.out.println("Visitor2%"+home1.getName());
   }

   @Override
   public void visit(Home2 home2) {
   	System.out.println("Visitor2%"+home2.getName());
   }

}

4.9 访问者分配者

package visitor.client;

import visitor.element.impl.Home1;
import visitor.element.impl.Home2;
import visitor.visit.impl.Visitor;
import visitor.visit.impl.Visitor1;
import visitor.visit.impl.Visitor2;

public class Main {

	public static void main(String[] args) {
		new Home1("home1").accept(new Visitor());
		new Home2("home2").accept(new Visitor());
		
		new Home1("home1").accept(new Visitor1());
		new Home2("home2").accept(new Visitor1());
		
		new Home1("home1").accept(new Visitor2());
		new Home2("home2").accept(new Visitor2());
	}

}

4.10 结果

accept#home1
visit#home1
accept#home2
visit#home2
accept#home1
visit&home1
accept#home2
visit&home2
accept#home1
Visitor2%home1
accept#home2
Visitor2%home2

5.知识点

5.1 双重分发

在例子中有两个方法:
visit
accept
其中:
数据.accept(访问者)
访问者.visit(数据)
这两个方法是相反的方法,这就是双重分发。
由数据和访问者共同决定调用实际的方法。

5.2 数据与处理分离

处理与数据分离,那么可以提高组件的复用性,数据是数据,处理是处理。

5.3 开闭原则

对扩展开放,对修改关闭。
对于访问者模式来说,增加一个访问者是一件非常轻松的事情,只需要实现访问者的接口即可。
但是对于数据来说,增加一个数据,则要修改所有的访问者,所以,对于访问者模式,增加操作简单,增加要处理的对象困难。

5.4 扩展

可以使用迭代器模式提供访问者提供数据
以及使用组合模式扩展访问者调用具体的数据
以及在访问者模式中增加模板方法模式等等。
23种设计模式

    原文作者:算法小白
    原文地址: https://blog.csdn.net/a18792721831/article/details/84590788
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞