访问者模式(Visitor Pattern)就是封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于其内部各个元素的新操作。通过访问者类改变元素类的执行算法,属于行为型模式。
通俗点说,就是用固定的结构,比如一个公司里就稳定十个人,根据公司不同的战略,这十个人要做不同的事情,普通实现的方式就是要建立不同的角色去做不同的事情,但是使用访问者模式后,我们就可以在不改变公司者十个人的前提下,去分别增加这十个人的各种角色去以干不同的事情。
再比如我响应国家号召生了两个子女已经很吃力了,不会改变家庭结构的前提下,我们用访问者模式来让两个娃娃去干不同的事情。
代码实现:
1.建立娃娃接口,造2娃娃
packagecom.xing.design.visitor.kid; importcom.xing.design.visitor.visitor.DoSomeVisitor; /*** 娃娃接口* @author xing*/publicinterfaceKid { voidaccept(DoSomeVisitorvisitor); } packagecom.xing.design.visitor.kid; importcom.xing.design.visitor.visitor.DoSomeVisitor; publicclassXiaoErimplementsKid{ privateStringname; publicStringgetName() { returnname; } publicXiaoEr(Stringname) { this.name=name; } publicvoidaccept(DoSomeVisitorvisitor) { visitor.visit(this); } } packagecom.xing.design.visitor.kid; importcom.xing.design.visitor.visitor.DoSomeVisitor; publicclassXiaoXiaoimplementsKid{ privateStringname; publicStringgetName() { returnname; } publicXiaoXiao(Stringname) { this.name=name; } publicvoidaccept(DoSomeVisitorvisitor) { visitor.visit(this); } }
2.建立做事情的访问类,有几个孩子元素,就有几个方法去访问他们
packagecom.xing.design.visitor.visitor; importcom.xing.design.visitor.kid.XiaoEr; importcom.xing.design.visitor.kid.XiaoXiao; publicinterfaceDoSomeVisitor { voidvisit(XiaoXiaoxiao); voidvisit(XiaoErxiao); }
实现访问类,可以访问到kid元素,去做不同的事情
packagecom.xing.design.visitor.visitor; importcom.xing.design.visitor.kid.XiaoEr; importcom.xing.design.visitor.kid.XiaoXiao; /*** 做事情 家务*/publicclassDoWorkSomeimplementsDoSomeVisitor{ publicvoidvisit(XiaoXiaoxiao) { System.out.println(xiao.getName()+"去洗碗..."); } publicvoidvisit(XiaoErxiao) { System.out.println(xiao.getName()+"去拖地..."); } } packagecom.xing.design.visitor.visitor; importcom.xing.design.visitor.kid.XiaoEr; importcom.xing.design.visitor.kid.XiaoXiao; /*** 学习* @author xing*/publicclassStudySomeimplementsDoSomeVisitor{ publicvoidvisit(XiaoXiaoxiao) { System.out.println(xiao.getName()+"去学手工..."); } publicvoidvisit(XiaoErxiao) { System.out.println(xiao.getName()+"去学散打..."); } }
3.建立不改变的数据结构类,这里我们就是家庭类,里面包含了存放孩子们的list,还有支持迭代获取孩子元素的的遍历访问方法调用。
packagecom.xing.design.visitor; importjava.util.ArrayList; importjava.util.List; importcom.xing.design.visitor.kid.Kid; importcom.xing.design.visitor.kid.XiaoEr; importcom.xing.design.visitor.kid.XiaoXiao; importcom.xing.design.visitor.visitor.DoSomeVisitor; /*** 家庭类* @author xing* @createTime 2022年3月11日*/publicclassFamily { privateList<Kid>kids=newArrayList<>(); publicFamily() { kids.add(newXiaoXiao("孝孝")); kids.add(newXiaoEr("小二")); } /*** 做事情* @param visitor*/publicvoiddoSome(DoSomeVisitorvisitor) { for(Kidkid : kids) { kid.accept(visitor); } } }
4.编写main方法测试
packagecom.xing.design.visitor; importcom.xing.design.visitor.visitor.DoWorkSome; importcom.xing.design.visitor.visitor.StudySome; publicclassVisitorDemo { publicstaticvoidmain(String[] args) { Familyfamily=newFamily(); System.out.println("------------今天大家做家务------------"); family.doSome(newDoWorkSome()); System.out.println("------------今天大家上补习班------------"); family.doSome(newStudySome()); } }
5.测试结果:
比如今天我想让大家一起去健身,明天大家一起去野餐,只要实现DoSomeVisitor 接口,就可以在实现类里分配不同的孩子去做不同的事情,并不需要去改Kid元素类,这就符合了开闭原则。
总结:
访问者模式主要解决的是稳定的数据结构(家里两个娃娃)和易变的操作(让两个孩子做不同的事情)的耦合问题。必须是数据结构稳定的时候才能使用。
END