访问者模式
表示一个作用于某对象结构中的各元素的操作。它使你在不改变各元素类的前提下定义作用于这些元素的新操作。
涉及到的角色描述
1、Visitor(抽象访问者):抽象访问者为对象结构中每一个具体元素类ConcreteElement声明一个访问操作,从这个操作的名称或参数类型可以清楚知道需要访问的具体元素的类型,具体访问者则需要实现这些操作方法,定义对这些元素的访问操作。
2、ConcreteVisitor(具体访问者):具体访问者实现了抽象访问者声明的方法,每一个操作作用于访问对象结构中一种类型的元素。
3、Element(抽象元素):一般是一个抽象类或接口,定义一个Accept方法,该方法通常以一个抽象访问者作为参数。
4、ConcreteElement(具体元素):具体元素实现了Accept方法,在Accept方法中调用访问者的访问方法以便完成一个元素的操作。
5、ObjectStructure(对象结构):对象结构是一个元素的集合,用于存放元素对象,且提供便利其内部元素的方法。
应用场景
1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。
2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作”污染”这些对象的类,也不希望在增加新操作时修改这些类。
优点
1、增加新的访问操作十分方便,不痛不痒 => 符合开闭原则
2、将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中,类的职责更加清晰 => 符合单一职责原则
缺点
1、增加新的元素类很困难,需要在每一个访问者类中增加相应访问操作代码 => 违背了开闭原则
2、元素对象有时候必须暴露一些自己的内部操作和状态,否则无法供访问者访问 => 破坏了元素的封装性
具体代码示例
抽象元素
package com.chenpt.designModel.visitorModel;
/**
* @Author: chen
* @Description: 抽象元素
* @Date: created in 2018/9/4
* @Modified By:
*/
public interface ComputerPart {
public void accept(ComputerPartVisitor computerPartVisitor);
}
具体元素1
package com.chenpt.designModel.visitorModel;
/**
* @Author: chen
* @Description:
* @Date: created in 2018/9/4
* @Modified By:
*/
public class Keyboard implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
具体元素2
package com.chenpt.designModel.visitorModel;
/**
* @Author: chen
* @Description:
* @Date: created in 2018/9/4
* @Modified By:
*/
public class Mouse implements ComputerPart {
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
computerPartVisitor.visit(this);
}
}
对象结构
package com.chenpt.designModel.visitorModel;
/**
* @Author: chen
* @Description:
* @Date: created in 2018/9/4
* @Modified By:
*/
public class Computer implements ComputerPart {
ComputerPart[] parts;
public Computer(){
parts = new ComputerPart[]{new Keyboard(),new Mouse()};
}
@Override
public void accept(ComputerPartVisitor computerPartVisitor) {
for (int i=0;i<parts.length;i++) {
parts[i].accept(computerPartVisitor);
}
computerPartVisitor.visit(this);
}
}
抽象访问者
package com.chenpt.designModel.visitorModel;
/**
* @Author: chen
* @Description: 抽象访问者
* @Date: created in 2018/9/4
* @Modified By:
*/
public interface ComputerPartVisitor {
// 声明一组重载的访问方法,用于访问不同类型的具体元素
void visit(Keyboard keyboard);
void visit(Mouse mouse);
void visit(Computer computer);
}
具体访问者
package com.chenpt.designModel.visitorModel;
/**
* @Author: chen
* @Description: 具体访问者
* @Date: created in 2018/9/4
* @Modified By:
*/
public class ComputerPartVisitorImpl implements ComputerPartVisitor {
@Override
public void visit(Keyboard keyboard) {
System.out.println("Displaying Keyboard.");
}
@Override
public void visit(Mouse mouse) {
System.out.println("Displaying Mouse.");
}
@Override
public void visit(Computer computer) {
System.out.println("Displaying Computer.");
}
}
客户端
package com.chenpt.designModel.visitorModel;
/**
* @Author: chen
* @Description:
* @Date: created in 2018/9/4
* @Modified By:
*/
public class MainTest {
public static void main(String[] args){
ComputerPart part = new Computer();
part.accept(new ComputerPartVisitorImpl());
}
}
//执行结果
Displaying Keyboard.
Displaying Mouse.
Displaying Computer.