【软件构造】再看JAVA的Visitor设计模式——如何兼顾可扩展性和防止表示泄露

何为Visitor设计模式?

访问者(Visitor)设计模式是指对特定类型的object的特定操作(visit),在运行时将二者动态绑定到一起,该操作可以灵活更改,无需更改被visit的类,本质上是将数据和作用于数据上的某种/些特定操作分离开来。

如何实现?

某个抽象数据类型想要实现Visitor设计模式,需要在ADT预留一个将来可扩展功能的“接入点”,外部实现的功能代码可以在不改变ADT本身的情况下通过delegation接入ADT。
举例而言,ADT内部需要预留一个接口函数,如:
public int accept(Visitor visitor);
该接口函数内部的实现也很简单:
visitor.visit(this);
这样,ADT将自己本身作为一个对象传入visitor的visit函数,由具体的各种不同的visitor的子类调用该ADT的具体方法灵活增加对ADT的各种不同操作(哪怕ADT没实现该操作)

我遇到的问题

在我的课程实验中,有这样一个任务要求:
请添加图片描述
poll是我自建的一个ADT,在其具体实现中,内部有一个私有字段Votes。其中包含有题目需求的“计算合法选票在所有选票中所占比例”这一信息,但poll中没有设计访问这一信息的方法。如果使用上述的Visitor设计模式,将poll本身传入visitor的visit函数,也无法访问私有字段。我的解决办法是:用于计算合法选票在所有选票中所占比例的具体的visitor的visit方法不再接受一整个poll对象,而是由poll在accept函数中,将自己的私有字段作为参数传递给visitor的visit方法:

@Override
public void accept(Visitor visitor) {
	if(visitor.getClass().equals(VotesVisitor.class))
		((VotesVisitor)visitor).visitPoll((Set)votes);
	else 
		visitor.visit(this);
}

后续如果再有对poll的私有字段的访问需求,也可以使用类似的方法实现。

潜在的问题

我们说,visitor是站在外部client的角度,灵活增加对ADT的各种不同操作,即用户可以自由地设计其所需的visitor对象,因此直接传入私有字段的方式很可能造成表示泄露。

解决方法

1.利用反射机制,通过类似 if(visitor.getClass().equals(VotesVisitor.class))
的语句判断该visitor是否是我们自己设计的无风险的Visitor,可以直接传入私有字段。否则正常地将自己本身(this)作为参数传递。
2.传入私有字段的防御式拷贝。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值