文章目录
- 一、访问者模式(Visitor Pattern)
- 二、文字描述
- 三、例子
- 例子一:菜鸟教程
- 对象定义
- 访问者定义
- 使用
- 总结
- 例子二:Spring的BeanDefinitionVisitor
一、访问者模式(Visitor Pattern)
行为型模式。
目的:将数据结构 与 数据操作分离。
二、文字描述
将对象属性的操作,交由Visitor对象进行操作。
三、例子
先说明一下。
个人认为访问者模式不一定非得按照菜鸟教程的例子来写,就像单例模式有好几种实现。
我们只需要将访问者的概念实现即可。
例子一:菜鸟教程
对象定义
public interface ComputerPart {public void accept(ComputerPartVisitor computerPartVisitor);
}
public class Monitor implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
public class Computer implements ComputerPart {private String data;@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
访问者定义
public interface ComputerPartVisitor {public void visit(Computer computer);public void visit(Monitor monitor);
}
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {@Overridepublic void visit(Computer computer) {System.out.println("Displaying Computer.");computer.data = "修改数据";}@Overridepublic void visit(Monitor monitor) {System.out.println("Displaying Monitor.");}
}
使用
ComputerPart computer = new Computer();
computer.accept(new ComputerPartDisplayVisitor());
总结
这个例子是菜鸟上的例子,已经被我简化了一下。
但是对于刚学这个模式的人来说,我感觉还是太绕了。
例子二:Spring的BeanDefinitionVisitor
这个Spring里面的一个类,个人认为这个比较好理解。
下面是BeanDefinitionVisitor的代码。
为了方便理解,代码比较长的方法已经被我删了,完整代码可以自己去spring看。
public class BeanDefinitionVisitor {@Nullableprivate StringValueResolver valueResolver;public BeanDefinitionVisitor(StringValueResolver valueResolver) {Assert.notNull(valueResolver, "StringValueResolver must not be null");this.valueResolver = valueResolver;}protected BeanDefinitionVisitor() {}protected void visitParentName(BeanDefinition beanDefinition) {String parentName = beanDefinition.getParentName();if (parentName != null) {String resolvedName = this.resolveStringValue(parentName);if (!parentName.equals(resolvedName)) {beanDefinition.setParentName(resolvedName);}}}protected void visitBeanClassName(BeanDefinition beanDefinition) {String beanClassName = beanDefinition.getBeanClassName();if (beanClassName != null) {String resolvedName = this.resolveStringValue(beanClassName);if (!beanClassName.equals(resolvedName)) {beanDefinition.setBeanClassName(resolvedName);}}}protected void visitFactoryBeanName(BeanDefinition beanDefinition) {String factoryBeanName = beanDefinition.getFactoryBeanName();if (factoryBeanName != null) {String resolvedName = this.resolveStringValue(factoryBeanName);if (!factoryBeanName.equals(resolvedName)) {beanDefinition.setFactoryBeanName(resolvedName);}}}protected void visitFactoryMethodName(BeanDefinition beanDefinition) {String factoryMethodName = beanDefinition.getFactoryMethodName();if (factoryMethodName != null) {String resolvedName = this.resolveStringValue(factoryMethodName);if (!factoryMethodName.equals(resolvedName)) {beanDefinition.setFactoryMethodName(resolvedName);}}}protected void visitScope(BeanDefinition beanDefinition) {String scope = beanDefinition.getScope();if (scope != null) {String resolvedScope = this.resolveStringValue(scope);if (!scope.equals(resolvedScope)) {beanDefinition.setScope(resolvedScope);}}}protected void visitPropertyValues(MutablePropertyValues pvs) {PropertyValue[] pvArray = pvs.getPropertyValues();PropertyValue[] var3 = pvArray;int var4 = pvArray.length;for(int var5 = 0; var5 < var4; ++var5) {PropertyValue pv = var3[var5];Object newVal = this.resolveValue(pv.getValue());if (!ObjectUtils.nullSafeEquals(newVal, pv.getValue())) {pvs.add(pv.getName(), newVal);}}}protected void visitArray(Object[] arrayVal) {for(int i = 0; i < arrayVal.length; ++i) {Object elem = arrayVal[i];Object newVal = this.resolveValue(elem);if (!ObjectUtils.nullSafeEquals(newVal, elem)) {arrayVal[i] = newVal;}}}protected void visitList(List listVal) {for(int i = 0; i < listVal.size(); ++i) {Object elem = listVal.get(i);Object newVal = this.resolveValue(elem);if (!ObjectUtils.nullSafeEquals(newVal, elem)) {listVal.set(i, newVal);}}}@Nullableprotected String resolveStringValue(String strVal) {if (this.valueResolver == null) {throw new IllegalStateException("No StringValueResolver specified - pass a resolver object into the constructor or override the 'resolveStringValue' method");} else {String resolvedValue = this.valueResolver.resolveStringValue(strVal);return strVal.equals(resolvedValue) ? strVal : resolvedValue;}}
}
这里就是用访问者的方法去设置BeanDefinition的属性,个人认为这个例子比较好理解。
简单粗暴,就是将数据结构和数据操作分离,BeanDefinition将设置属性的操作交给了BeanDefinitionVisitor 操作。