访问者模式是比较难理解的一种设计模式。。。 至少对我来说
访问者模式的定义为:封装一些作用于某种 数据结构中的各元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
我自己的访问者代码:
package InvolvedMode.visitor; import java.util.ArrayList; import java.util.List; /** * VisitorTest : 访问者模式 * @author xuejupo [email protected] * create in 2015-12-30 下午1:47:25 */ public class VisitorTest { /** * main: * @param args * void 返回类型 */ public static void main(String[] args) { // TODO Auto-generated method stub Men wangdachui = new Men(); //王大锤想去家乐福 wangdachui.addPublicAreas(new Carrefour()); //王大锤想去夜店 wangdachui.addPublicAreas(new Club()); //王大锤逛自己的公共场所 wangdachui.display(); } } /** * goods: 一个商品接口 * @author xuejupo [email protected] * create in 2015-12-30 下午1:52:16 * */ interface goods{ } /** * apple: 苹果是商品,只有price属性 * @author xuejupo [email protected] * create in 2015-12-30 下午1:55:46 * */ class Apple implements goods{ double price; } /** * orange:橘子也是商品 * @author xuejupo [email protected] * create in 2015-12-30 下午1:56:19 * */ class Orange implements goods{ double price; } /** * publicAreas: 公共场所统一接口 * @author xuejupo [email protected] * create in 2015-12-30 下午2:15:21 * */ interface PublicAreas{ /** * accept: 所有的公共场所都要接待来访者 * @param vistor * void 返回类型 */ void accept(IVistor vistor); } /** * market: 商场接口 * @author xuejupo [email protected] * create in 2015-12-30 下午1:59:03 * */ interface Market extends PublicAreas{ /** * sellApple: 商场可以卖苹果 * void 返回类型 */ void sellApple(); /** * sellOrange: 商场也可以卖橘子 * void 返回类型 */ void sellOrange(); } /** * Carrefour: 家乐福商场 * @author xuejupo [email protected] * create in 2015-12-30 下午2:01:10 * */ class Carrefour implements Market{ //家乐福的商品 private goods apple = new Apple(); private goods orange = new Orange(); @Override public void sellApple() { // TODO Auto-generated method stub System.out.println("我卖苹果,新鲜"); } @Override public void sellOrange() { // TODO Auto-generated method stub System.out.println("我卖橘子,新鲜"); } @Override public void accept(IVistor vistor) { // TODO Auto-generated method stub vistor.visit(this); } } /** * Club: 夜店,也算一个公共场所 * @author xuejupo [email protected] * create in 2015-12-30 下午2:16:32 * */ class Club implements PublicAreas{ /** * hasGirl: 男人去夜店关心什么? 有没有美女 * void 返回类型 */ public void hasGirl(){ System.out.println("这里只有芙蓉,玉凤!"); } @Override public void accept(IVistor vistor) { // TODO Auto-generated method stub vistor.visit(this); } } /** * IVistor:访问者接口 * @author xuejupo [email protected] * create in 2015-12-30 下午2:12:06 * */ interface IVistor{ void visit(Carrefour carrefour); void visit(Club club); } /** * Vostor: 访问者 * @author xuejupo [email protected] * create in 2016-1-5 下午7:10:50 * */ class Vistor implements IVistor{ /** * 去超市,关心的是有没有苹果卖 */ public void visit(Carrefour carrefour) { // TODO Auto-generated method stub carrefour.sellOrange(); } /** * 去夜店,关心的是有没有美女 */ public void visit(Club club) { // TODO Auto-generated method stub club.hasGirl(); } } /** * people: 人类接口 * @author xuejupo [email protected] * create in 2015-12-30 下午2:22:50 * */ interface people{ } class Men implements people{ //每个男人都有自己想去的公共场所 private List<PublicAreas> l; private IVistor vistor = new Vistor(); public Men(){ l = new ArrayList<PublicAreas>(); } /** * setVistor: 设置访问者对象 * @param vistor * void 返回类型 */ public void setVistor(IVistor vistor){ this.vistor = vistor; } /** * addPublicAreas: 增加自己想去的公共场所 * @param p * void 返回类型 */ public void addPublicAreas(PublicAreas p){ this.l.add(p); } /** * display: 去自己想去的公共场所逛逛 * void 返回类型 */ public void display(){ for(PublicAreas p:l){ p.accept(vistor); } } }
结果:
我卖橘子,新鲜 这里只有芙蓉,玉凤!
个人想法:
设计模式之禅上的例子是最适合于访问者模式了。首先,他的数据结构基本已经定了,数据结构基本就那么几种,包含元素也已经上线稳定。但是在数据结构稳定的前提下,对数据结构的操作还有修改和扩展,这种形式比较适合用访问者模式。
比如上面的代码,假设数据结构已经稳定了,超市只卖橘子,夜店只有玉凤和芙蓉,那么如果王大锤突然变重口(变更数据结构的操作)想去夜店找玉凤,那么只需增加一个访问者类:
class Vistor implements IVistor{ /** * 去夜店,找玉凤 */ public void visit(Club club) { // TODO Auto-generated method stub System.out.println("玉凤看起来很美~~~"); club.getGirl(); } }
然后调用王大锤的set方法即可,不需要修改现有类,这是比较好的方式。
但是。。。。 这里有两个设定,一是现有数据结构基本不变并且针对数据结构的操作可能会有变更;二是项目在设计之初就已经用了访问者模式了(这点比较难)。。 因为数据结构稳定就意味着项目已经设计编码基本完毕,如果项目设计之初没有使用访问者模式,那要用它可能就要修改所有代码。。。 这显然是很2的。。。 而项目设计之初就用他。。。 感觉也有点22的。。。。 总觉得这个模式很鸡肋。。 如果有什么不对的,希望大神能留言提点