1,访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式,这就是访问者模式的动机。

Dec 29, 2014 4:39:44 PM
2,UML图:
3,访问者角色:
IElement:抽象的事物元素功能接口,定义了固定功能方法以及可变功能方法接口。
Element:具体功能的实现类。
IVisitor:访问者接口,为所有访问者对象声明一个visit方法,用来代表为对象结构添加的功能,原则上可以代表任意功能。
Visitor:具体访问实现类,实现要正真被添加到对象结构中的功能。
4,基本代码例子:
/** * * @(#) IShape.java * @Package pattern.chp09.visitor.simple * * Copyright © JING Corporation. All rights reserved. * */ package pattern.chp09.visitor.simple; /** * 类描述:抽象需求接口 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 2:40:16 PM Jing Created. * */public interface IShape { /** * * 方法说明:获取图形面积 * * Author: Jing * Create Date: Dec 29, 2014 2:40:41 PM * * @return * @return float */ float getArea(); /** * * 方法说明:获取周长 * * Author: Jing * Create Date: Dec 29, 2014 2:41:04 PM * * @return * @return float */ float getLength(); /** * * 方法说明:传入访问者对象和方法名 * * Author: Jing * Create Date: Dec 29, 2014 2:43:17 PM * * @param v * @return * @return Object */ Object accept(IVisitor v);}/** * * @(#) Triangle.java * @Package pattern.chp09.visitor.simple * * Copyright © JING Corporation. All rights reserved. * */ package pattern.chp09.visitor.simple; /** * 类描述:三角形 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 2:45:54 PM Jing Created. * */public class Triangle implements IShape { float x1, y1, x2, y2, x3, y3;// 三角形三点坐标 public Triangle(float x1, float y1, float x2, float y2, float x3, float y3) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; this.x3 = x3; this.y3 = y3; } public Object accept(IVisitor v) { return v.visit(this); } public float getArea() { float a = getDist(x1, y1, x2, y2); float b = getDist(x1, y1, x3, y3); float c = getDist(x2, y2, x3, y3); float s = (a + b + c) / 2; return (float) Math.sqrt(s * (s - a) * (s - b) * (s - c)); } public float getLength() { float a = getDist(x1, y1, x2, y2); float b = getDist(x1, y1, x3, y3); float c = getDist(x2, y2, x3, y3); return a + b + c; } /** * * 方法说明:求任意两点距离 * * Author: Jing Create Date: Dec 29, 2014 2:49:51 PM * * @param u1 * @param v1 * @param u2 * @param v2 * @return * @return float */ public float getDist(float u1, float v1, float u2, float v2) { return (float) Math.sqrt((u1 - u2) * (u1 - u2) + (v1 - v2) * (v1 - v2)); } }/** * * @(#) IVisitor.java * @Package pattern.chp09.visitor.simple * * Copyright © JING Corporation. All rights reserved. * */ package pattern.chp09.visitor.simple; /** * 类描述:访问者接口 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 2:42:28 PM Jing Created. * */public interface IVisitor { /** * * 方法说明:访问方法 * * Author: Jing * Create Date: Dec 29, 2014 2:46:48 PM * * @param t * @return * @return Object */ Object visit(Triangle t);}/** * * @(#) Point.java * @Package pattern.chp09.visitor.simple * * Copyright © JING Corporation. All rights reserved. * */ package pattern.chp09.visitor.simple; /** * 类描述:重心类坐标 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 3:06:50 PM Jing Created. * */public class Point { float x, y;}/** * * @(#) CenterVisitor.java * @Package pattern.chp09.visitor.simple * * Copyright © JING Corporation. All rights reserved. * */ package pattern.chp09.visitor.simple; /** * 类描述:重心坐标实现 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 3:07:37 PM Jing Created. * */public class CenterVisitor implements IVisitor { public Object visit(Triangle t) { Point pt = new Point(); pt.x = (t.x1 + t.x2 + t.x3) / 3; pt.y = (t.y1 + t.y2 + t.y3) / 3; return pt; } }/** * * @(#) Test.java * @Package pattern.chp09.visitor.simple * * Copyright © JING Corporation. All rights reserved. * */ package pattern.chp09.visitor.simple; /** * 类描述: * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 3:09:31 PM Jing Created. * */public class Test { public static void main(String[] args) { IVisitor v = new CenterVisitor();// 定义重心具体访问者对象 Triangle t = new Triangle(0, 0, 2, 0, 0, 2); Point pt = (Point) t.accept(v); System.out.println(pt.x + ", " + pt.y);//输出重心 System.out.println(t.getArea());//输出面积 }}5,深入理解访问者模式:如上的代码,如果三角形需要增加n个功能,则必须定义n个具体访问者类,使用反射可以更新代码,对Visitor接口和子类进行修改即可:
package pattern.chp09.visitor.deep; /** * 类描述:访问者接口 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 3:32:50 PM Jing Created. * */public interface IVisitor { /** * * 方法说明:访问对象对应的方法 * * Author: Jing Create Date: Dec 29, 2014 3:34:58 PM * * @param t * @param method * @return * @return Object */ Object visit(Triangle t, String method);} package pattern.chp09.visitor.deep; import java.lang.reflect.Method; import pattern.chp09.visitor.simple.Point; /** * 类描述:图形类 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 3:40:25 PM Jing Created. * */public class ShapVisitor implements IVisitor { /** * * 方法说明:获取重心坐标 * * Author: Jing Create Date: Dec 29, 2014 3:41:05 PM * * @param t * @return * @return Object */ public Object getCenter(Triangle t) { Point p = new Point(); p.x = (t.x1 + t.x2 + t.x3) / 3; p.y = (t.y1 + t.y2 + t.y3) / 3; return p; } /** * * 方法说明:内切圆半径 * * Author: Jing Create Date: Dec 29, 2014 3:46:09 PM * * @param t * @return * @return Float */ public Float getInnerCircleR(Triangle t) { float area = t.getArea(); float len = t.getLength(); return new Float(2.0F * area / len); } public Object visit(Triangle t, String method) { Object result = null; try { Class<?> clazz = this.getClass(); Method m = clazz.getMethod(method, Triangle.class); result = m.invoke(this, new Object[] { t }); } catch (Exception e) { e.printStackTrace(); } return result; } }/** * 类描述: * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 4:02:35 PM Jing Created. * */public class Test { public static void main(String[] args) { IVisitor v = new ShapVisitor(); Triangle t = new Triangle(0,0,2,0,0,2); Point p = (Point) t.accept(v, "getCenter"); System.out.println(p.x + ", " + p.y); Float f = (Float) t.accept(v, "getInnerCircleR"); System.out.println(f.floatValue()); }}6,构建集合对象自适应功能框架:
完成一个对应银行和存单管理的例子。
package pattern.chp09.visitor.bank; /** * 类描述:银行存单管理 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 5:06:27 PM Jing Created. * */public abstract class Bank { public void accept(IVisitor<Bank> v){ v.visit(this); } /** * * 方法说明:执行存折 * * Author: Jing * Create Date: Dec 29, 2014 5:09:40 PM * * @param visit * @return void */ public abstract void process(IVisitor<Sheet> visit);} package pattern.chp09.visitor.bank; /** * 类描述:存单 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 4:34:10 PM Jing Created. * */public abstract class Sheet { String account;// 帐号 String name;// 姓名 float money;// 余额 String startDate;// 存款日期 int range;// 期限 public Sheet(String account, String name, float money, String startDate, int range) { this.account = account; this.name = name; this.money = money; this.startDate = startDate; this.range = range; } /** * * 方法说明:访问对象方法 * * Author: Jing * Create Date:package pattern.chp09.visitor.bank; /** * 类描述:泛型访问者接口 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 4:31:53 PM Jing Created. * */public interface IVisitor<T> { /** * * 方法说明:访问方法 * * Author: Jing * Create Date: Dec 29, 2014 4:33:26 PM * * @param s * @return void */ void visit(T s);} * * @param v * @return void */ public void accept(IVisitor<Sheet> v) { v.visit(this); } } package pattern.chp09.visitor.bank; import java.util.Vector; /** * 类描述:农行 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 5:10:52 PM Jing Created. * */public class ABCBank extends Bank { Vector<ABCSheet> v = new Vector<ABCSheet>(); /** * * 方法说明:增加存单 * * Author: Jing * Create Date: Dec 29, 2014 5:11:37 PM * * @param s * @return void */ void add(ABCSheet s){ v.add(s); } @Override public void process(IVisitor<Sheet> visit) { for(int i = 0; i <v.size();i++){ v.get(i).accept(visit); } } } package pattern.chp09.visitor.bank; /** * 类描述:农行 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 5:06:05 PM Jing Created. * */public class ABCSheet extends Sheet { public ABCSheet(String account, String name, float money, String startDate, int range) { super(account, name, money, startDate, range); } } package pattern.chp09.visitor.bank; import java.util.Vector; /** * 类描述:工行 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 5:15:17 PM Jing Created. * */public class ICBCBank extends Bank { Vector<ICBCsheet> v = new Vector<ICBCsheet>(); @Override public void process(IVisitor<Sheet> visit) { for (int i = 0; i < v.size(); i++) { v.get(i).accept(visit); } } /** * * 方法说明:增加存单 * * Author: Jing * Create Date: Dec 29, 2014 5:16:16 PM * * @param s * @return void */ void add(ICBCsheet s){ v.add(s); } }package pattern.chp09.visitor.bank; /** * 类描述:工行存单子类 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 5:03:41 PM Jing Created. * */public class ICBCsheet extends Sheet { public ICBCsheet(String account, String name, float money, String startDate, int range) { super(account, name, money, startDate, range); } } package pattern.chp09.visitor.bank; import java.util.Vector; /** * 类描述:银行组存单管理 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 5:18:01 PM Jing Created. * */public class BankGroup { Vector<Bank> v = new Vector<Bank>(); /** * * 方法说明:增加银行 * * Author: Jing * Create Date: Dec 29, 2014 5:20:57 PM * * @param bank * @return void */ void add(Bank bank){ v.add(bank); } public void accept(IVisitor<BankGroup> v){ v.visit(this); } public void process(IVisitor<Bank> visit){ for(Bank bg: v){ bg.accept(visit); } }} package pattern.chp09.visitor.bank; /** * 类描述:存单 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 4:34:10 PM Jing Created. * */public abstract class Sheet { String account;// 帐号 String name;// 姓名 float money;// 余额 String startDate;// 存款日期 int range;// 期限 public Sheet(String account, String name, float money, String startDate, int range) { this.account = account; this.name = name; this.money = money; this.startDate = startDate; this.range = range; } /** * * 方法说明:访问对象方法 * * Author: Jing * Create Date: Dec 29, 2014 4:39:44 PM * * @param v * @return void */ public void accept(IVisitor<Sheet> v) { v.visit(this); } }定义一个存单访问者以及一个银行访问者。
package pattern.chp09.visitor.bank; /** * 类描述:账单访问类 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 5:38:42 PM Jing Created. * */public class SheetVisitor implements IVisitor<Sheet> { private void ABCProc(ABCSheet s){ System.out.println("ABCSheet process"); } private void ICBCProc(ICBCsheet s){ System.out.println("ICBCSheet process"); } public void visit(Sheet s) { if (s instanceof ABCSheet) { ABCProc((ABCSheet)s); } if (s instanceof ICBCsheet) { ICBCProc((ICBCsheet)s); } }} package pattern.chp09.visitor.bank; /** * 类描述:银行访问者 * * @author: Jing * @version $Id: Exp$ * * History: Dec 29, 2014 5:45:45 PM Jing Created. * */public class BankVisitor implements IVisitor<Bank> { private void ABCProc(ABCBank b) { System.out.println("ABCBank process"); } private void ICBCProc(ICBCBank b) { System.out.println("ICBCBank process"); } public void visit(Bank s) { if (s instanceof ABCBank) { ABCProc((ABCBank) s); } if (s instanceof ICBCBank) { ICBCProc((ICBCBank) s); } } }package pattern.chp09.visitor.bank; /** * 类描述: * * @author: Jing * @version $Id: Exp$ * * History: Dec 30, 2014 10:28:23 AM Jing Created. * */public class Test { public static void main(String[] args) { ICBCsheet s = new ICBCsheet("1000", "liu", 100, "2014-1-1", 3); IVisitor v = new SheetVisitor(); s.accept(v); ICBCBank manage = new ICBCBank(); manage.add(s); manage.process(v); }}