a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 146|回复: 2

[基础知识] Java基础:Visitor模式

[复制链接]
发表于 2012-8-4 12:37:27 | 显示全部楼层 |阅读模式
Visitor 定义
+ w" j) P  N+ B# G* |  作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作.& m: N" n1 s8 |3 ?4 q
  在Java 中,Visitor 模式实际上是分离了collection 结构中的元素和对这些元素进行操作的行为.
5 Q  j# F5 l: }  j9 l2 @, X! [0 {  为何使用Visitor?
. _5 k4 p+ [3 J- F, c  U" }( e  Java 的Collection(包括Vector 和Hashtable)是我们最经常使用的技术,可是Collection好象是个黑色大染缸,本来有各种鲜明类型特征的对象一旦放入后,再取出时,这些类型就消失了.那么我们势必要用If 来判断,如:
9 W4 Z0 F  S& J4 d  Iterator iterator = collection.iterator()
1 B$ I8 H; K* t  while (iterator.hasNext()) {( N8 C" e6 W1 s& m; w5 e
  Object o = iterator.next();
1 J! A9 H( q( V; O( d# Y. l& e: x  if (o instanceof Collection)! ~; ^9 M2 b% i2 R
  messyPrintCollection((Collection)o);" c) A) K: a4 w# k0 d, W) U1 f4 x
  else if (o instanceof String)
' U* z: M- s5 [  System.out.println("'"+o.toString()+"'");
, d% n; \. {. P7 \; V9 B  else if (o instanceof Float); ^" P7 X! y* E+ J3 V
  System.out.println(o.toString()+"f");1 T% _, i% D0 S
  else
7 n; z+ z) _$ p, O. i  System.out.println(o.toString());
1 {# T7 D5 s/ @2 t0 k. Q3 g* t  }
1 l( J* l4 c1 G  在上例中,我们使用了 instanceof 来判断 o 的类型.
1 a$ E1 n$ N7 e& u, x6 W6 l  很显然,这样做的缺点代码If else if 很繁琐.我们就可以使用Visitor 模式解决它.
+ K2 v  @2 L6 c' M7 {! O/ w# @# z- c1 t  如何使用Visitor?  [0 @- W3 i& y' f# g
  针对上例,我们设计一个接口visitor 访问者:% B3 \& `. o' }9 E! q
  public interface Visitor
2 }" M8 h9 Y$ A- ]+ A( P; t7 l% F  {
( `$ V' Q( t8 t. |" E% P# J0 p# C( t3 G0 ^
  
回复

使用道具 举报

 楼主| 发表于 2012-8-4 12:37:28 | 显示全部楼层

Java基础:Visitor模式

public void visitCollection(Collection collection);</p>  public void visitString(String string);
" L6 e2 Q; ?  ^) y  public void visitFloat(Float float);. D7 t+ d2 E. g$ P8 V
  }$ z" m. H  o. u$ H8 Z0 ]
  在这个接口中,将我们认为Collection 有可能的类的类型放入其中.; ^8 T% {  L$ r/ J: `  o8 P4 E3 J
  有了访问者,我们需要被访问者,被访问者就是我们Collection 的每个元素Element,我们要为这些Element 定义一个可以接受访问的接口(访问和被访问是互动的,只有访问者,被访问者如果表示不欢迎,访问者就不能访问),我们定义这个接口叫Visitable, 用来定义一个Accept 操作,也就是说让Collection 每个元素具备可访问性.1 F3 i2 B! N+ k  x; {1 W3 U% c
  public interface Visitable5 [/ Z6 p4 |! I
  {; f( d0 P! N1 y" e
  public void accept(Visitor visitor);
& q. f! H( n( D  ~4 @, j) D  T  }
9 s! Q8 c: K7 n6 Q& o: L) w8 I5 x! f  好了,有了两个接口,我们就要定义他们的具体实现(Concrete class):
# |& e) p, t4 ~  public class ConcreteElement implements Visitable
5 Y' Q( \1 e3 C' N) A, Q/ }' V% `  {
% f! w4 M+ H/ d* q$ z  private String value;+ S0 n. n+ ?+ h* G! }. m# l
  public ConcreteElement(String string) {% {  `  D7 W6 m& A9 J
  value = string;
- A+ u- g& F: F8 d* j- D  }- f% @* Q7 C6 w- s+ ]# X9 D( S5 w
  //定义accept 的具体内容 这里是很简单的一句调用0 L% \( w* k* k. s7 l- |
  public void accept(Visitor visitor) {( [# Q% l* D' b6 o3 H5 |
  visitor.visitString(this);
. F' `) H" I7 P8 c2 V% w9 B2 ]# j- L  }  L: [2 w2 ~- f- A, V
  }+ a, @% t) S! X7 `6 m, |
  再看看访问者的Concrete 实现:
, Y2 E/ s$ @: h5 J  y) @  public class ConcreteVisitor implements Visitor
/ ~+ M# _" ^$ q, n0 @  {9 E8 E0 L+ X: L  P+ t: w8 ]. E
7 r2 c+ e* b0 q5 l5 J" Z( z: C) n- ?
 
回复 支持 反对

使用道具 举报

 楼主| 发表于 2012-8-4 12:37:29 | 显示全部楼层

Java基础:Visitor模式

 //在本方法中,我们实现了对Collection 的元素的成功访问</p>  public void visitCollection(Collection collection) {
( j% X* E) m1 y8 P( j# c  Iterator iterator = collection.iterator()
4 n8 R6 U  }& d4 w  ^  while (iterator.hasNext()) {
2 z1 \* O  S, e8 {: U  Object o = iterator.next();' v2 r0 F, Z9 B# \+ ]. u
  if (o instanceof Visitable)
( I3 E$ J# Z+ D. ?1 c, q0 m  ((Visitable)o).accept(this);% E  ]- h5 B; R# ~
  }
4 }# x) m" M- E" d; c  public void visitString(String string) {
, ]' Z" n. K1 a" C/ s/ R; N  System.out.println("'"+string+"'");
, i0 {, y3 n: ?& A/ K/ H8 O6 S% z  }
5 ~( S3 O% _4 R) C* q4 l  public void visitFloat(Float float) {$ r' _% p  R- U8 z8 Y3 p7 K( O' q
  System.out.println(float.toString()+"f");
, Z1 s0 B' r( m  }
0 e" Z6 d1 j/ d8 k  }  P1 u  L9 H+ Y' _5 d
  }
  x0 d6 j# D( ^: R; b6 T# w3 D$ d  在上面的visitCollection 我们实现了对Collection 每个元素访问,只使用了一个判断语句,只要判断其是否可以访问.
: y  H5 ?- {, B6 X8 B9 A8 x  至此,我们完成了Visitor 模式基本架构.
8 A3 Z  J# k3 y5 i  使用Visitor 模式的前提
9 g4 U: M( P' P- K7 o8 J& Y  对象群结构中(Collection) 中的对象类型很少改变,也就是说访问者的身份类型很少改变,如上面中Visitor 中的类型很少改变,如果需要增加新的操作,比如上例中我们在ConcreteElement 具体实现外,还需要新的ConcreteElement2 ConcreteElement3.
. [) x2 }' J+ i: x  可见使用Visitor 模式是有前提的,在两个接口Visitor 和Visitable 中,确保Visitor 很少变化,变化的是Visitable,这样使用Visitor 最方便.
1 \$ O0 ?$ ~) |# P* b. r  如果Visitor 也经常变化, 也就是说,对象群中的对象类型经常改变,一般建议是,不如在这些对象类中逐个定义操作.但是Java 的Reflect 技术解决了这个问题.
6 _: J0 w+ N4 g; N1 R- \3 W1 i8 m  Reflect 技术是在运行期间动态获取对象类型和方法的一种技术,具体实现参考Javaworld的英文原文.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-4-29 19:18 , Processed in 0.193495 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表