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


23种设计模式

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

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

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

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

2.访问者模式中的角色

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

3.关系

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

4.例子

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

4.1结构图

在这里插入图片描述

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种设计模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值