Jay*_*Jay 2 java visitor-pattern
Alrite,我会直接跳到代码:
public interface Visitor {
public void visitInventory();
public void visitMaxCount();
public void visitCountry();
public void visitSomethingElse();
public void complete();
//the idea of this visitor is that when a validator would visit it, it would validate data
//when a persister visits it, it would persist data, etc, etc.
// not sure if I making sense here...
}
public interface Visitable {
public void accept(Visitor visitor);
}
Run Code Online (Sandbox Code Playgroud)
这是一个基础实现:
public class StoreValidator implements Visitor {
private List <ValidationError> storeValidationErrors = new ArrayList<ValidationError>();
public void addError(ValidationError error) {
storeValidationErrors.add(error);
}
public List<ValidationError> getErrors() {
return storeValidationErrors;
}
public void visitInventory() {
// do nothing
}
public void visitMaxCount() {
//do nothing
}
//... etc.. all empty implementations
}
Run Code Online (Sandbox Code Playgroud)
你会明白为什么我在这里做了一个空的实现...我现在会写一个验证器..它扩展了StoreValidator
public XYZValidator extends StoreValidator {
@Override
public void visitInventory(Visitable visitable) {
// do something with visitable .. cast it to expected type
// invoke a DAO, obtain results from DB
// if errors found, do addError(new ValidationError()); with msg.
}
@Override
public void visitMaxCount(Visitable visitable) {
//do something with visitable..
}
// I wouldn't implement the rest coz they wouldn't make sense
// in XYZValidator.. so they are defined as empty in StoreValidator.
}
Run Code Online (Sandbox Code Playgroud)
现在这是一个可访问的样子:
public Store implements Visitable {
public void accept(Visitor visitor) {
visitor.visitInventory();
visitor.visitMaxCount();
}
}
Run Code Online (Sandbox Code Playgroud)
我可以在Store对象列表中使用类似的代码:
List<Store> stores; //assume this has a list of stores.
StoreValidator validator = new XYZValidator(); //or I would get it from a validatorfactory
for(Store store: stores) {
store.accept(validator); // so even if you send a wrong validator, you are good.
}
Run Code Online (Sandbox Code Playgroud)
类似地,您将拥有ABCValidator,它将为其他方法(visitCountry/visitSomethinElse)提供实现,并且它将从StoreValidator扩展.我会有另一种类型的Object(而不是Store)定义accept方法.
我确实在这里看到一个问题...说,我需要一个与StoreValidator不同的FileValidator,我希望它没有这些与业务相关的验证,例如visitInventory()等.但是,通过一个接口访问者,我最终会在Visitor接口中声明各种方法.那是对的吗?这是你怎么做的?
我不知道我的模式是否错误,或者我是否有任何意义.请分享你的想法.
前段时间我为我的硕士论文写了类似的东西.此代码比您的代码略微安全:
interface Visitable<T extends Visitor> {
void acceptVisitor(T visitor);
}
interface Visitor {
/**
* Called before any other visiting method.
*/
void startVisit();
/**
* Called at the end of the visit.
*/
void endVisit();
}
Run Code Online (Sandbox Code Playgroud)
例:
interface ConstantPoolVisitor extends Visitor {
void visitUTF8(int index, String utf8);
void visitClass(int index, int utf8Index);
// ==cut==
}
class ConstantPool implements Visitable<ConstantPoolVisitor> {
@Override
public void acceptVisitor(ConstantPoolVisitor visitor) {
visitor.startVisit();
for (ConstanPoolEntry entry : entries) {
entry.acceptVisitor(visitor);
}
visitor.endVisit();
}
Run Code Online (Sandbox Code Playgroud)
所以是的,我认为这绝对是一个良好而灵活的设计,如果且仅当您的数据变化慢于您的行为时.在我的示例中,数据是Java字节码,它是固定的(由JVM规范定义).当"行为支配"(我想转储,编译,转换,重构等我的字节码)时,访问者模式允许您更改/添加/删除行为而不触及您的数据类.只需添加另一个Visitor实现.
为了简单起见,假设我必须向访问者界面添加另一个访问方法:我最终会破坏我的所有代码.
作为替代方案,我会考虑这种情况的策略模式.策略+装饰器是一个很好的验证设计.