导读:简介.访问者模式(Visitor.Pattern)是一种行为型模式。它封装一个访问者类,把各元素类的操作集合起来,目的是将数据结构与数据操作分离。在不改变原有元素类数据结构的前提下,改变了元素类的执行算法。.当某些较为稳定的东西(数据结构或算法),不想直接被改变但又想扩展功能,这
访问者模式(Visitor Pattern)是一种行为型模式。它封装一个访问者类,把各元素类的操作集合起来,目的是将数据结构与数据操作分离。在不改变原有元素类数据结构的前提下,改变了元素类的执行算法。
当某些较为稳定的东西(数据结构或算法),不想直接被改变但又想扩展功能,这时候适合用访问者模式。访问者模式的使用频率并不是很高,大多数情况下,你并不需要使用访问者模式,但是当你一旦需要使用它时,那你就是需要使用它了。
访问者模式有以下几个角色:
// ObjectStructure.java 结构对象(ObjectStructure)
public class ObjectStructure {
// 可以想象为一台电脑,聚合了各种设备元素
private String name = "Computer Structure";
private List<Element> elements = new ArrayList<Element>();
// 结构对象初始化聚合了其他元素
public ObjectStructure() {
addElement(new ConcreteElementA());
addElement(new ConcreteElementB());
}
public void addElement(Element element) {
elements.add(element);
}
// 传入访问者分发给其他元素
public void accept(Visitor visitor) {
System.out
.println("ObjectStructure::accept() [visitor.class = " + visitor.getClass().getSimpleName() + " visitor.name = "
+ visitor.getName() + "]");
for (Element element : elements) {
element.accept(visitor);
}
}
public String getName() {
return this.name;
}
}
// Visitor.java 访问者Visitor抽象接口,定义不同的visit方法
public interface Visitor {
public void visit(ConcreteElementA concreteElementA);
public void visit(ConcreteElementB concreteElementB);
public String getName();
}
// ConcreteVisitorA.java 具体访问者A
public class ConcreteVisitorA implements Visitor {
// 假如由不同厂商是程序的访问者
private String name = "Google Visitor";
@Override
public void visit(ConcreteElementA concreteElementA) {
System.out.println(
"ConcreteVisitorA::visit() [Element.class = " + concreteElementA.getClass().getSimpleName()
+ " Element.name = "
+ concreteElementA.getName() + "]");
concreteElementA.operate();
}
@Override
public void visit(ConcreteElementB concreteElementB) {
System.out.println("ConcreteVisitorA::visit() [Element.class = " + concreteElementB.getClass().getSimpleName()
+ " Element.name = "
+ concreteElementB.getName() + "]");
concreteElementB.operate();
}
public String getName() {
return this.name;
}
}
// ConcreteVisitorB.java 具体访问者B
public class ConcreteVisitorB implements Visitor {
// 假如由不同厂商是程序的访问者
private String name = "Apple Visitor";
@Override
public void visit(ConcreteElementA concreteElementA) {
System.out.println(
"ConcreteVisitorB::visit() [Element.class = " + concreteElementA.getClass().getSimpleName()
+ " Element.name = "
+ concreteElementA.getName() + "]");
concreteElementA.operate();
}
@Override
public void visit(ConcreteElementB concreteElementB) {
System.out.println(
"ConcreteVisitorB::visit() [Element.class = " + concreteElementB.getClass().getSimpleName()
+ " Element.name = "
+ concreteElementB.getName() + "]");
concreteElementB.operate();
}
public String getName() {
return this.name;
}
}
// Element.java 抽象元素(Element),定义accept方法,传入抽象访问者
abstract class Element {
public abstract void accept(Visitor visitor);
}
// ConcreteElementA.java 具体的元素实现者A
public class ConcreteElementA extends Element {
// 可以设想为显示器
private String name = "Monitor Element";
@Override
public void accept(Visitor visitor) {
System.out
.println(
"ConcreteElementA::accept() [visitor.class = " + visitor.getClass().getSimpleName() + " visitor.name = "
+ visitor.getName() + "]");
visitor.visit(this);
}
public void operate() {
System.out.println("ConcreteElementA::operate() [" + this.getName() + "]");
}
public String getName() {
return this.name;
}
}
// ConcreteElementB.java 具体的元素实现者B
public class ConcreteElementB extends Element {
private String name = "Keyboard Element";
@Override
public void accept(Visitor visitor) {
System.out.println(
"ConcreteElementB::accept() [visitor.class = " + visitor.getClass().getSimpleName() + " visitor.name = "
+ visitor.getName() + "]");
visitor.visit(this);
}
public void operate() {
System.out.println("ConcreteElementB::operate() [" + this.getName() + "]");
}
public String getName() {
return this.name;
}
}
/**
* 访问者模式是当客户需要访问具体各元素Element时,先建立一个访问者Visitor作为媒介
* 客户基于对象结构ObjectStructure,调用accept(),接受传入的访问者
* 对象结构向其他元素负责分发访问者,元素对象接受之后会将自己回传给访问者,从而访问者可以访问具体元素
*/
ObjectStructure structure = new ObjectStructure();
// 接受访问者A,把访问者传递给具体元素
structure.accept(new ConcreteVisitorA());
System.out.println("====");
// 接受访问者B,把访问者传递给具体元素
structure.accept(new ConcreteVisitorB());
// ObjectStructure.go 结构对象(ObjectStructure)
type ObjectStructure struct {
name string
elements []Element
}
func (o *ObjectStructure) AddElement(e Element) {
o.elements = append(o.elements, e)
}
// 传入访问者分发给其他元素
func (o *ObjectStructure) Accept(v Visitor) {
fmt.Println(
"ObjectStructure::Accept() [Visitor.name = " +
v.GetName() + "]")
// 通知全部元素成员接受访问者
for i := 0; i < len(o.elements); i++ {
o.elements[i].Accept(v)
}
// for _, ele := range o.elements {
// ele.Accept(v)
// }
}
func (o *ObjectStructure) GetName() string {
o.name = "Computer Structure"
return o.name
}
// 结构对象的初始化函数
func (o *ObjectStructure) Init() {
// 可以想象为一台电脑,聚合了各种设备元素
fmt.Println("ObjectStructure::Init() ", o.GetName())
// 定义一个对象数组,长度可选
o.elements = make([]Element, 0, 100)
// 结构对象初始化聚合了其他元素
o.AddElement(&ConcreteElementA{})
o.AddElement(&ConcreteElementB{})
}
// Visitor.go 访问者Visitor抽象接口,定义不同的visit方法
type Visitor interface {
VisitA(e *ConcreteElementA)
VisitB(e *ConcreteElementB)
GetName() string
}
// ConcreteVisitorA.go 具体访问者A
type ConcreteVisitorA struct {
name string
}
func (v *ConcreteVisitorA) GetName() string {
v.name = "Google Visitor(struct=ConcreteVisitorA)"
return v.name
}
func (v *ConcreteVisitorA) VisitA(e *ConcreteElementA) {
fmt.Println(
"ConcreteVisitorA::VisitA() [Element.name = " + e.GetName() + "]")
e.Operate()
}
func (v *ConcreteVisitorA) VisitB(e *ConcreteElementB) {
fmt.Println(
"ConcreteVisitorA::VisitB() [Element.name = " + e.GetName() + "]")
e.Operate()
}
// ConcreteVisitorB.go 具体访问者B
type ConcreteVisitorB struct {
name string
}
func (v *ConcreteVisitorB) GetName() string {
v.name = "Apple Visitor(struct=ConcreteVisitorB)"
return v.name
}
func (v *ConcreteVisitorB) VisitB(e *ConcreteElementB) {
fmt.Println(
"ConcreteVisitorB::VisitB() [Element.name = " + e.GetName() + "]")
e.Operate()
}
func (v *ConcreteVisitorB) VisitA(e *ConcreteElementA) {
fmt.Println(
"ConcreteVisitorB::VisitA() [Element.name = " + e.GetName() + "]")
e.Operate()
}
// Element.go 抽象元素(Element),定义accept方法,传入抽象访问者
// go无抽象类,用interface替代
type Element interface {
Accept(v Visitor)
Operate()
GetName() string
}
// ConcreteElementA.go 具体的元素实现者A
type ConcreteElementA struct {
name string
}
func (c *ConcreteElementA) GetName() string {
c.name = `Monitor Element(struct=ConcreteElementA)`
return c.name
}
func (e *ConcreteElementA) Accept(v Visitor) {
fmt.Println(
"ConcreteElementA::Accept() [Visitor.name = " + v.GetName() + "]")
v.VisitA(e)
}
func (e *ConcreteElementA) Operate() {
fmt.Println("ConcreteElementA::Operate() [" + e.GetName() + "]")
}
// ConcreteElementB.go 具体的元素实现者B
type ConcreteElementB struct {
name string
}
func (c *ConcreteElementB) GetName() string {
c.name = "Keyboard Element(struct=ConcreteElementB)"
return c.name
}
func (e *ConcreteElementB) Accept(v Visitor) {
fmt.Println(
"ConcreteElementB::Accept() [Visitor.name = " + v.GetName() + "]")
v.VisitB(e)
}
func (e *ConcreteElementB) Operate() {
fmt.Println("ConcreteElementB::Operate() [" + e.GetName() + "]")
}
func main() {
fmt.Println("test start:")
/**
* 访问者模式是当客户需要访问具体各元素Element时,先建立一个访问者Visitor作为媒介
* 客户基于对象结构ObjectStructure,调用Accept(),接受传入的访问者
* 对象结构向其他元素负责分发访问者,元素对象接受之后会将自己回传给访问者,从而访问者可以访问具体元素
*/
structure := src.ObjectStructure{}
structure.Init()
// 接受访问者A,把访问者传递给具体元素
structure.Accept(&src.ConcreteVisitorA{})
fmt.Println("====")
// 接受访问者B,把访问者传递给具体元素
structure.Accept(&src.ConcreteVisitorB{})
}
不同语言设计模式源码:https://github.com/microwind/design-pattern
上一篇:山河大学:一所跨越山河,笑对未来
下一篇:设计模式(四)建造者