Java 相关课程的多个访问者
我正在简化一些东西,以指出我的基本设计问题 我有这样的层次结构:Java 相关课程的多个访问者,java,design-patterns,architecture,visitor,visitor-pattern,Java,Design Patterns,Architecture,Visitor,Visitor Pattern,我正在简化一些东西,以指出我的基本设计问题 我有这样的层次结构: R <-- interface / \ / \ / \ BR RR <-- abstract classes / | \ / | \ / | \ / | \ BRA BR
R <-- interface
/ \
/ \
/ \
BR RR <-- abstract classes
/ | \ / | \
/ | \ / | \
BRA BRB BRC RRA RRB RRC <-- classes
public interface R {
/* . . . */
}
public abstract class BR implements R {
/* . . . */
public abstract void accept(VisitorBR vbr);
}
public abstract class RR implements R {
/* . . . */
public abstract void accept(VisitorRR vrr);
}
public class BRA extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class BRB extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class BRC extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class RRA extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class RRB extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class RRC extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class Client implements Runnable {
private VisitorBR vbr;
private VisitorRR vrr;
private BlockingQueue<R> q;
/* . . . */
@Override
void run() {
for (;;) {
R r = q.take();
/*** Somehow handle r with the most suitable visitor, ***/
/*** based on whether it's descendant of BR or RR. ***/
}
}
}
@Override
void run() {
for (;;) {
R r = q.take();
if (r.getType() == BR)
((BR) r).accept(vbr);
else // if (r.getType() == RR)
((RR) r).accept(vrr)
}
}
public abstract class BR implements R {
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorBR vbr);
}
public abstract class RR implements R {
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorRR vrr);
}
public class SelectiveVisitor {
private VisitorBR vbr;
private VisitorRR vrr;
public SelectiveVisitor(VisitorBR vbr, VisitorRR vrr) {
this.vbr = vbr;
this.vrr = vrr;
}
public void visit(R r) {
// this method should never be called in practice
// it's here only to satisfy the selective visitor pattern
return;
}
public void visit(BR r) {
r.accept(this.vbr);
}
public void visit(RR r) {
r.accept(this.vrr);
}
}
及
客户机类有一个
BlockingQueue
,对每个访问者类的一个对象有一个引用,并且需要使用最合适的访问者处理队列的所有元素。看起来像这样:
R <-- interface
/ \
/ \
/ \
BR RR <-- abstract classes
/ | \ / | \
/ | \ / | \
BRA BRB BRC RRA RRB RRC <-- classes
public interface R {
/* . . . */
}
public abstract class BR implements R {
/* . . . */
public abstract void accept(VisitorBR vbr);
}
public abstract class RR implements R {
/* . . . */
public abstract void accept(VisitorRR vrr);
}
public class BRA extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class BRB extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class BRC extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class RRA extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class RRB extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class RRC extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class Client implements Runnable {
private VisitorBR vbr;
private VisitorRR vrr;
private BlockingQueue<R> q;
/* . . . */
@Override
void run() {
for (;;) {
R r = q.take();
/*** Somehow handle r with the most suitable visitor, ***/
/*** based on whether it's descendant of BR or RR. ***/
}
}
}
@Override
void run() {
for (;;) {
R r = q.take();
if (r.getType() == BR)
((BR) r).accept(vbr);
else // if (r.getType() == RR)
((RR) r).accept(vrr)
}
}
public abstract class BR implements R {
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorBR vbr);
}
public abstract class RR implements R {
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorRR vrr);
}
public class SelectiveVisitor {
private VisitorBR vbr;
private VisitorRR vrr;
public SelectiveVisitor(VisitorBR vbr, VisitorRR vrr) {
this.vbr = vbr;
this.vrr = vrr;
}
public void visit(R r) {
// this method should never be called in practice
// it's here only to satisfy the selective visitor pattern
return;
}
public void visit(BR r) {
r.accept(this.vbr);
}
public void visit(RR r) {
r.accept(this.vrr);
}
}
但是必须有一个更优雅的解决方案来组合两个访问者类。这里是一个访问者模式的示例。请注意,这里有一个界面访问者,它为每种类型的访问点提供了
visit()
方法
public class Demo {
public static void main ( String [] args ) {
Point p = new Point2d( 1, 2 );
Visitor v = new Chebyshev();
p.accept( v );
System.out.println( p.getMetric() );
}
}
interface Visitor {
public void visit ( Point2d p );
public void visit ( Point3d p );
}
abstract class Point {
public abstract void accept ( Visitor v );
private double metric = -1;
public double getMetric () {
return metric;
}
public void setMetric ( double metric ) {
this.metric = metric;
}
}
class Point2d extends Point {
public Point2d ( double x, double y ) {
this.x = x;
this.y = y;
}
public void accept ( Visitor v ) {
v.visit( this );
}
private double x;
public double getX () { return x; }
private double y;
public double getY () { return y; }
}
class Point3d extends Point {
public Point3d ( double x, double y, double z ) {
this.x = x;
this.y = y;
this.z = z;
}
public void accept ( Visitor v ) {
v.visit( this );
}
private double x;
public double getX () { return x; }
private double y;
public double getY () { return y; }
private double z;
public double getZ () { return z; }
}
class Euclid implements Visitor {
public void visit ( Point2d p ) {
p.setMetric( Math.sqrt( p.getX()*p.getX() + p.getY()*p.getY() ) );
}
public void visit ( Point3d p ) {
p.setMetric( Math.sqrt( p.getX()*p.getX() + p.getY()*p.getY() + p.getZ()*p.getZ() ) );
}
}
class Chebyshev implements Visitor {
public void visit ( Point2d p ) {
double ax = Math.abs( p.getX() );
double ay = Math.abs( p.getY() );
p.setMetric( ax>ay ? ax : ay );
}
public void visit ( Point3d p ) {
double ax = Math.abs( p.getX() );
double ay = Math.abs( p.getY() );
double az = Math.abs( p.getZ() );
double max = ax>ay ? ax : ay;
if ( max<az ) max = az;
p.setMetric( max );
}
}
公共类演示{
公共静态void main(字符串[]args){
点p=新点2D(1,2);
访客v=新切比雪夫();
p、 接受(v);
System.out.println(p.getMetric());
}
}
界面访问者{
公众访问(点2D p);
公众访问(Point3d p);
}
抽象类点{
公开摘要无效接受(访客v);
私有双指标=-1;
公共双getMetric(){
返回度量;
}
公共无效集合度量(双度量){
this.metric=metric;
}
}
类Point2d扩展了Point{
公共点2D(双x,双y){
这个.x=x;
这个。y=y;
}
公众无效接受(访客v){
v、 访问(本);
}
私人双x;
公共双getX(){return x;}
私人双y;
公共双getY(){return y;}
}
类Point3d扩展了Point{
公共点3D(双x、双y、双z){
这个.x=x;
这个。y=y;
这个。z=z;
}
公众无效接受(访客v){
v、 访问(本);
}
私人双x;
公共双getX(){return x;}
私人双y;
公共双getY(){return y;}
私人双z;
公共双getZ(){return z;}
}
类Euclid实现访问者{
公众访问(点2D p){
p、 setMetric(Math.sqrt(p.getX()*p.getX()+p.getY()*p.getY());
}
公众无效访问(Point3d p){
p、 setMetric(Math.sqrt(p.getX()*p.getX()+p.getY()*p.getY()+p.getZ()*p.getZ());
}
}
类Chebyshev实现了Visitor{
公众访问(点2D p){
double ax=Math.abs(p.getX());
double-ay=Math.abs(p.getY());
p、 setMetric(ax>ay?ax:ay);
}
公众无效访问(Point3d p){
double ax=Math.abs(p.getX());
double-ay=Math.abs(p.getY());
double az=Math.abs(p.getZ());
双倍最大值=ax>ay?ax:ay;
if(max这里是一个访问者模式的示例。请注意,这里是一个界面访问者,它对每种类型的访问点使用visit()
方法
public class Demo {
public static void main ( String [] args ) {
Point p = new Point2d( 1, 2 );
Visitor v = new Chebyshev();
p.accept( v );
System.out.println( p.getMetric() );
}
}
interface Visitor {
public void visit ( Point2d p );
public void visit ( Point3d p );
}
abstract class Point {
public abstract void accept ( Visitor v );
private double metric = -1;
public double getMetric () {
return metric;
}
public void setMetric ( double metric ) {
this.metric = metric;
}
}
class Point2d extends Point {
public Point2d ( double x, double y ) {
this.x = x;
this.y = y;
}
public void accept ( Visitor v ) {
v.visit( this );
}
private double x;
public double getX () { return x; }
private double y;
public double getY () { return y; }
}
class Point3d extends Point {
public Point3d ( double x, double y, double z ) {
this.x = x;
this.y = y;
this.z = z;
}
public void accept ( Visitor v ) {
v.visit( this );
}
private double x;
public double getX () { return x; }
private double y;
public double getY () { return y; }
private double z;
public double getZ () { return z; }
}
class Euclid implements Visitor {
public void visit ( Point2d p ) {
p.setMetric( Math.sqrt( p.getX()*p.getX() + p.getY()*p.getY() ) );
}
public void visit ( Point3d p ) {
p.setMetric( Math.sqrt( p.getX()*p.getX() + p.getY()*p.getY() + p.getZ()*p.getZ() ) );
}
}
class Chebyshev implements Visitor {
public void visit ( Point2d p ) {
double ax = Math.abs( p.getX() );
double ay = Math.abs( p.getY() );
p.setMetric( ax>ay ? ax : ay );
}
public void visit ( Point3d p ) {
double ax = Math.abs( p.getX() );
double ay = Math.abs( p.getY() );
double az = Math.abs( p.getZ() );
double max = ax>ay ? ax : ay;
if ( max<az ) max = az;
p.setMetric( max );
}
}
公共类演示{
公共静态void main(字符串[]args){
点p=新点2D(1,2);
访客v=新切比雪夫();
p、 接受(v);
System.out.println(p.getMetric());
}
}
界面访问者{
公众访问(点2D p);
公众访问(Point3d p);
}
抽象类点{
公开摘要无效接受(访客v);
私有双指标=-1;
公共双getMetric(){
返回度量;
}
公共无效集合度量(双度量){
this.metric=metric;
}
}
类Point2d扩展了Point{
公共点2D(双x,双y){
这个.x=x;
这个。y=y;
}
公众无效接受(访客v){
v、 访问(本);
}
私人双x;
公共双getX(){return x;}
私人双y;
公共双getY(){return y;}
}
类Point3d扩展了Point{
公共点3D(双x、双y、双z){
这个.x=x;
这个。y=y;
这个。z=z;
}
公众无效接受(访客v){
v、 访问(本);
}
私人双x;
公共双getX(){return x;}
私人双y;
公共双getY(){return y;}
私人双z;
公共双getZ(){return z;}
}
类Euclid实现访问者{
公众访问(点2D p){
p、 setMetric(Math.sqrt(p.getX()*p.getX()+p.getY()*p.getY());
}
公众无效访问(Point3d p){
p、 setMetric(Math.sqrt(p.getX()*p.getX()+p.getY()*p.getY()+p.getZ()*p.getZ());
}
}
类Chebyshev实现了Visitor{
公众访问(点2D p){
double ax=Math.abs(p.getX());
double-ay=Math.abs(p.getY());
p、 setMetric(ax>ay?ax:ay);
}
公众无效访问(Point3d p){
double ax=Math.abs(p.getX());
double-ay=Math.abs(p.getY());
double az=Math.abs(p.getZ());
双倍最大值=ax>ay?ax:ay;
如果(max好的话,我想我现在已经想出了更好的办法,灵感来自于。然而,我仍然对优雅的解决方案持开放态度
定义了一个新类SelectiveVisitor
,它现在是Client
拥有的访问者类的唯一引用。InterfaceR
现在声明了一个附加方法:
public interface R {
/* . . . */
public accept(SelectiveVisitor sv);
}
因此,BR
和RR
修改如下:
R <-- interface
/ \
/ \
/ \
BR RR <-- abstract classes
/ | \ / | \
/ | \ / | \
BRA BRB BRC RRA RRB RRC <-- classes
public interface R {
/* . . . */
}
public abstract class BR implements R {
/* . . . */
public abstract void accept(VisitorBR vbr);
}
public abstract class RR implements R {
/* . . . */
public abstract void accept(VisitorRR vrr);
}
public class BRA extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class BRB extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class BRC extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class RRA extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class RRB extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class RRC extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class Client implements Runnable {
private VisitorBR vbr;
private VisitorRR vrr;
private BlockingQueue<R> q;
/* . . . */
@Override
void run() {
for (;;) {
R r = q.take();
/*** Somehow handle r with the most suitable visitor, ***/
/*** based on whether it's descendant of BR or RR. ***/
}
}
}
@Override
void run() {
for (;;) {
R r = q.take();
if (r.getType() == BR)
((BR) r).accept(vbr);
else // if (r.getType() == RR)
((RR) r).accept(vrr)
}
}
public abstract class BR implements R {
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorBR vbr);
}
public abstract class RR implements R {
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorRR vrr);
}
public class SelectiveVisitor {
private VisitorBR vbr;
private VisitorRR vrr;
public SelectiveVisitor(VisitorBR vbr, VisitorRR vrr) {
this.vbr = vbr;
this.vrr = vrr;
}
public void visit(R r) {
// this method should never be called in practice
// it's here only to satisfy the selective visitor pattern
return;
}
public void visit(BR r) {
r.accept(this.vbr);
}
public void visit(RR r) {
r.accept(this.vrr);
}
}
新类的定义如下:
R <-- interface
/ \
/ \
/ \
BR RR <-- abstract classes
/ | \ / | \
/ | \ / | \
BRA BRB BRC RRA RRB RRC <-- classes
public interface R {
/* . . . */
}
public abstract class BR implements R {
/* . . . */
public abstract void accept(VisitorBR vbr);
}
public abstract class RR implements R {
/* . . . */
public abstract void accept(VisitorRR vrr);
}
public class BRA extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class BRB extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class BRC extends BR {
/* . . . */
public void accept(VisitorBR vbr) { vbr.visit(this); }
}
public class RRA extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class RRB extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class RRC extends RR {
/* . . . */
public void accept(VisitorRR vrr) { vrr.visit(this); }
}
public class Client implements Runnable {
private VisitorBR vbr;
private VisitorRR vrr;
private BlockingQueue<R> q;
/* . . . */
@Override
void run() {
for (;;) {
R r = q.take();
/*** Somehow handle r with the most suitable visitor, ***/
/*** based on whether it's descendant of BR or RR. ***/
}
}
}
@Override
void run() {
for (;;) {
R r = q.take();
if (r.getType() == BR)
((BR) r).accept(vbr);
else // if (r.getType() == RR)
((RR) r).accept(vrr)
}
}
public abstract class BR implements R {
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorBR vbr);
}
public abstract class RR implements R {
/* . . . */
public void accept(SelectiveVisitor sv) {
sv.visit(this);
}
public abstract void accept(VisitorRR vrr);
}
public class SelectiveVisitor {
private VisitorBR vbr;
private VisitorRR vrr;
public SelectiveVisitor(VisitorBR vbr, VisitorRR vrr) {
this.vbr = vbr;
this.vrr = vrr;
}
public void visit(R r) {
// this method should never be called in practice
// it's here only to satisfy the selective visitor pattern
return;
}
public void visit(BR r) {
r.accept(this.vbr);
}
public void visit(RR r) {
r.accept(this.vrr);
}
}
客户端
现在更改为:
public class Client implements Runnable {
private SelectiveVisitor sv;
private BlockingQueue<R> q;
/* . . . */
@Override
void run() {
for (;;) {
R r = q.take();
r.accept(sv);
}
}
}
公共类客户端实现可运行{
私家侦探;
私有阻塞队列q;
/* . . . */
@凌驾
无效运行(){
对于(;;){
R=q.take();
r、 接受(sv);
}
}
}
每次调用r.accept(selectiveVisitor)
时,selectiveVisitor
类的visit
方法由BR
和RR
的子类之一调用
类SelectiveVisitor
的visit
方法重载。每次调用它时,都会动态选择最具体的版本,从而选择最合适的访问者访问r
我要离开这里了,