Java设计模式之访问者模式使用场景及代码示例
Java设计模式访问者模式
模式概念
访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。访问者模式适用于数据结构相对稳定算法又易变化的系统,若系统数据结构对象易于变化,则不适合使用访问者模式。访问者模式的优点是增加操作很容易,因为增加操作意味着增加新的访问者。
Visitor应用场景
一定会有的疑问:visitor和iterator的区别:
visitor可以访问不同的对象(只需要在Element定义对应的accept),但是Iterator只能访问相同的对象,最起码要有相同的接口
iterator是不依赖具体实现的,而visitor是依赖具体实现的,因为Visitor会根据访问的具体的对象来采取对应的操作,而iterator最多只是基于相同的接口的泛化实现。
iterator访问的数据结构的操作和数据并未分离,所以拓展功能起来需要修改,违反了开闭原则和单一职责原则。但是因为访问者依赖具体实现,而不是依赖抽象,所以违反了依赖倒置原则
优缺点决定的应用场景
符合单一职责原则,功能上具有良好的拓展性,但是因为依赖具体实现违背了具体实现,所以为类的修改带了麻烦。
具有优良的拓展性,只需要实现新的Visitor来满足新的访问要求。因为数据和操作的分离,防止了添加新的操作污染原来的数据结构。
综上
访问者是一种集中规整模式,特别适合用于大规模重构的项目,在这一个阶段的需求已经非常清晰,原系统的功能点也已经明确,通过访问者模式可以很容易把一些功能进行梳理,达到最终目的功能集中化
模式结构
1)Visitor抽象访问者角色:
为该对象结构中具体元素角色声明一个访问操作接口。该操作接口的名字和参数标识了发送访问请求给具体访问者的具体元素角色,这样访问者就可以通过该元素角色的特定接口直接访问它。
2)ConcreteVisitor具体访问者角色:
实现Visitor声明的接口。
3)Element抽象受访元素:
定义一个接受访问操作(accept()),它以一个访问者(Visitor)作为参数。
4)ConcreteElement具体受访元素:
实现了抽象元素(Element)所定义的接受操作接口。
5)ObjectStructure结构对象角色:
这是使用访问者模式必备的角色。它具备以下特性:能枚举它的元素;可以提供一个高层接口以允许访问者访问它的元素;如有需要,可以设计成一个复合对象或者一个聚集(如一个列表或无序集合)。
Demo
抽象访问者角色:
publicinterfaceIVisitor{
publicvoidaccept(Femanfeman);
publicvoidaccept(Manman);
}
具体访问角色:
publicclassVisitorimplementsIVisitor{
publicvoidaccept(Femanfeman){
System.out.println(feman.getSex()+":执行相关操作");
}
publicvoidaccept(Manman){
System.out.println(man.getSex()+":执行相关操作");
}
}
(注)Visitor中设置了同样的名称的方法且方法传参为实现同一接口的不同对象,即受访者元素。
抽象受访元素:
publicabstractclassPerson{
privateStringsex;
publicStringgetSex(){
returnsex;
}
publicvoidsetSex(Stringsex){
this.sex=sex;
}
publicvoidaccept(Visitorvisitor){
};
}
具体受访元素:
publicclassManextendsPerson{
publicMan(){
this.setSex("男");
}
@Override
publicvoidaccept(Visitorvisitor){
visitor.accept(this);
}
}
publicclassFemanextendsPerson{
publicFeman(){
this.setSex("女");
}
@Override
publicvoidaccept(Visitorvisitor){
visitor.accept(this);
}
}
结构对象角色:
publicclassObjectStruture{
publicstaticListgetList(){
Listlist=newArrayList();
list.add(newMan());
list.add(newFeman());
list.add(newFeman());
returnlist;
}
}
执行过程:
Visitorvisitor=newVisitor(); Listlist=ObjectStruture.getList(); for(Persone:list){ e.accept(visitor); }
执行结果:
男:执行相关操作 女:执行相关操作 女:执行相关操作
下面是一个完整的代码示例:
publicinterfaceVisitor
{
publicvoidvisit(GladiolusConcreteElementgladiolus);
publicvoidvisit(ChrysanthemumConreteElementchrysanthemum);
}
publicinterfaceFlowerElement
{
publicvoidaccept(Visitorvisitor);
}
publicclassGladiolusConcreteElementimplementsFlowerElement
{
@Override
publicvoidaccept(finalVisitorvisitor)
{
visitor.visit(this);
}
}
publicclassChrysanthemumConreteElementimplementsFlowerElement
{
@Override
publicvoidaccept(finalVisitorvisitor)
{
visitor.visit(this);
}
}
publicclassGladiolusVisitorimplementsVisitor
{
@Override
publicvoidvisit(finalGladiolusConcreteElementgladiolus)
{
System.out.println(this.getClass().getSimpleName()+"access"+gladiolus.getClass().getSimpleName());
}
@Override
publicvoidvisit(finalChrysanthemumConreteElementchrysanthemum)
{
System.out.println(this.getClass().getSimpleName()+"access"+chrysanthemum.getClass().getSimpleName());
}
}
publicclassChrysanthemumConreteElementimplementsFlowerElement
{
@Override
publicvoidaccept(finalVisitorvisitor)
{
visitor.visit(this);
}
}
publicclassObjectStructure
{
privatefinalListelements=newArrayList();
publicvoidaddElement(finalFlowerElemente)
{
elements.add(e);
}
publicvoidremoveElement(finalFlowerElemente)
{
elements.remove(e);
}
publicvoidaccept(finalVisitorvisitor)
{
for(finalFlowerElemente:elements)
{
e.accept(visitor);
}
}
}
publicclassClient
{
publicstaticvoidmain(finalString[]args)
{
finalObjectStructureos=newObjectStructure();
os.addElement(newGladiolusConcreteElement());
os.addElement(newChrysanthemumConreteElement());
finalGladiolusVisitorgVisitor=newGladiolusVisitor();
finalChrysanthemumVisitorchVisitor=newChrysanthemumVisitor();
os.accept(gVisitor);
os.accept(chVisitor);
}
}
运行结果:
GladiolusVisitoraccessGladiolusConcreteElement GladiolusVisitoraccessChrysanthemumConreteElement ChrysanthemumVisitoraccessGladiolusConcreteElement ChrysanthemumVisitoraccessChrysanthemumConreteElement
总结
以上就是本文关于Java设计模式之访问者模式使用场景及代码示例的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站:Java编程—在测试中考虑多态、Java实现微信公众平台朋友圈分享功能详细代码、Java编程BigDecimal用法实例分享等,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持。