读书笔记_java设计模式深入研究 第九章 访问者模式 Vistor

1,访问者模式的目的是封装一些施加于某种数据结构元素之上的操作,一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。为不同类型的元素提供多种访问操作方式,且可以在不修改原有系统的情况下增加新的操作方式,这就是访问者模式的动机。
2,UML图:
读书笔记_java设计模式深入研究 第九章  访问者模式  Vistor
读书笔记_java设计模式深入研究 第九章  访问者模式  Vistor
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);
}

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;
 
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);
}
}