Java设计模式-访问者模式

最近学习到设计模式,现总结个人学习访问者模式内容【注重的是稳定的数据结构和易变的操作耦合问题】。
上一篇:Java设计模式-命令模式

定义

一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。【简单的说就是下例中的添加的口罩对象没有修改,只是访问者(病毒改变了),而改变了执行结果】。
二次理解:您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。【您是访问者,你朋友是被访问者(他可以有多人个人访问他),每一个人对他的评价是不一致的,】

优缺点

优点

  • 符合单一职责原则。
  • 优秀的扩展性。
  • 灵活性

缺点

  • 具体元素对访问者公布细节,违反了迪米特原则。
  • 具体元素变更比较困难。
  • 违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

实现

访问者模式大致类图(来源于网络)
在这里插入图片描述
角色介绍

  • Visitor【下例中的病毒接口】:接口或者抽象类,定义了对每个 Element
    访问的行为,它的参数就是被访问的元素它的方法个数理论上与元素的个数是一样的,因此,访问者模式要求元素的类型要稳定,如果经常添加、移除元素类,必然会导致频繁地修改 Visitor 接口,如果出现这种情况,则说明不适合使用访问者模式。
  • ConcreteVisitor【下例中的具体病毒】:具体的访问者,它需要给出对每一个元素类访问时所产生的具体行为。
  • Element【下例中的口罩】:元素接口或者抽象类,它定义了一个接受访问者(accept)的方法,其意义是指每一个元素都要可以被访问者访问。
  • ElementA、ElementB【下例中的具体口罩】:具体的元素类,它提供接受访问的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。
  • ObjectStructure:定义当中所提到的对象结构,对象结构是一个抽象表述,它内部管理了元素集合,并且可以迭代这些元素提供访问者访问。

代码大概类图
在这里插入图片描述

代码

被访问者接口或实现类,以及具体被访问者

/**被访问者
 * 口罩抽象类、或者接口
 * 提供病毒访问口罩的隔离方法
 * @author cc百川
 */
public abstract class Mask {
	//提供一个方法,让访问者可以访问
	public abstract void accept(VirusVisitors visitor);
}
//n95口罩 具体被访问者
class N95Mask extends Mask{
	@Override
	public void accept(VirusVisitors visitor) {
		System.out.println("n95口罩拦截病毒...");
		visitor.N95MaskFilteringResult(this);
	}
}

//医用口罩 具体被访问者
class MedicalMask extends Mask{
	@Override
	public void accept(VirusVisitors visitor) {
		System.out.println("医用口罩拦截病毒");
	}
}
//一次性口罩 具体被访问者
class OnceMask extends Mask{
	@Override
	public void accept(VirusVisitors visitor) {
		System.out.println("一次性口罩拦截病毒");
		visitor.OnceMaskFilteringResult(this);
	}
}

访问者

/** 病毒访问者
 * @author cc百川
 *定义了对每个Element(Mask-口罩)访问的行为,
 *它的参数就是被访问的元素(对象的口罩类型),它的方法个数理论上与元素(口罩类型)的个数是一样的,
 *它的修改是很复杂的,所以这一块应该是稳定的,尽量少的修改【接口或者抽象类添加抽象方法,所有实现类都需要调整】
 */
public abstract class VirusVisitors {
	public abstract void N95MaskFilteringResult(N95Mask n95);
	public abstract void Medical(MedicalMask medical);
	public abstract void OnceMaskFilteringResult(OnceMask once);
}

//新型冠状名都访问者
class N2019nCoV extends VirusVisitors{
	@Override
	public void N95MaskFilteringResult(N95Mask n95) {
		System.out.println("2019nCoV想通过口罩进入人体,N95口罩拦截了");
	}
	@Override
	public void Medical(MedicalMask medical) {
		System.out.println("2019nCoV想通过口罩进入人体,医用口罩口罩拦截中,长时间使用这个口罩,不更换容易拦截失效");
		medical.accept(this);
	}
	@Override
	public void OnceMaskFilteringResult(OnceMask once) {
		System.out.println("2019nCoV想通过口罩进入人体,一次性口罩拦失敗");
	}
}
//甲型流感病毒访问者
class H1N1Virus extends VirusVisitors{
	@Override
	public void N95MaskFilteringResult(N95Mask n95) {
		System.out.println("h1n1想通过口罩进入人体,N95口罩拦截了");
	}
	@Override
	public void Medical(MedicalMask medical) {
		System.out.println("h1n1想通过口罩进入人体,医用口罩口罩拦截了");
		medical.accept(this);
	}
	@Override
	public void OnceMaskFilteringResult(OnceMask once) {
		System.out.println("h1n1想通过口罩进入人体,一次性口罩拦可能失敗");
	}
}

维护结构对象,封装被访问者集合,提供迭代访问者访问

/**
 * ObjectStructure:定义当中所提到的对象结构,对象结构是一个抽象表述,
 * 它内部管理了元素集合,并且可以迭代这些元素提供访问者访问
 * @author cc百川
 */
public class ObjectStructure {
	//维护了一个集合管理被访问者
	private List<Mask> masks = new LinkedList<>();
	//增加访问者
	public void addMask(Mask mask) {
		masks.add(mask);
	} 
	//显示测评情况
	public void display(VirusVisitors visitor) {
		for(Mask mask: masks) {
			mask.accept(visitor);
		}
	}
}

测试

在这里插入图片描述


访问者模式重点在于稳定的数据结构和易变的操作耦合问题
以上仅为个人学习,如果错误望指出,谢谢。

发布了81 篇原创文章 · 获赞 40 · 访问量 6万+
App 阅读领勋章
微信扫码 下载APP
阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览