Gof23种设计模式(23)——访问者模式(Visitor)

2020年8月14日10:25:57 评论 79

1 基础知识

1.1 标准定义

访问者(Visitor)模式标准定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

1.2 分析和说明

访问者(Visitor)模式属于对象行为型模式。访问者模式的目的是封装一些施加于某种数据结构元素之上的操作。一旦这些操作需要修改的话,接受这个操作的数据结构可以保持不变。访问者模式适用于数据结构相对未定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由的演化。访问者模式使得增加新的操作变的很容易,就是增加一个新的访问者类。访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。当使用访问者模式时,要将尽可能多的对象浏览逻辑放在访问者类中,而不是放到它的子类中。访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。

访问者(Visitor)模式结构如图1所示,其角色包括抽象访问者(Visitor)角色、具体访问者(Concrete Visitor)角色、抽象节点(Node)角色、具体节点(Node)角色和结构对象(Object Structure)角色。

Gof23种设计模式(23)——访问者模式(Visitor)图1 访问者模式结构

 抽象访问者(Visitor)角色:声明了一个或者多个访问操作,形成所有的具体元素角色必须实现的接口。

 具体访问者(Concrete Visitor)角色:实现抽象访问者角色所声明的接口,也就是抽象访问者所声明的各个访问操作。

 抽象节点(Node)角色:声明一个接受操作,接受一个访问者对象作为一个参量。

 具体节点(Node)角色:实现了抽象元素所规定的接受操作。

 结构对象(Object Structure)角色:有如下的一些责任,可以遍历结构中的所有元素;如果需要,提供一个高层次的接口让访问者对象可以访问每一个元素;如果需要,可以设计成一个复合对象或者一个聚集,如列(List)或集合(Set)。

2 应用场景举例

比如公司一般都要接受多方面的审查,对于工商部门,看看是否符合商务审计。对于税务部门,看看是否合法纳税。对于会计师事务所,要对公司进行财务审计。这些部门都是外部的参观者。抽象访问者(Visitor)角色:工商部门、税务部门和会计师事务所是具体访问者角色。定义一个抽象公司的抽象节点角色。不同的公司工商情况,税务情况和会计情况就是具体节点角色。用例如图2所示。

Gof23种设计模式(23)——访问者模式(Visitor)图2 访问者模式类图

在这里可以把Visitor抽象类理解为抽象访问者(Visitor)角色。AccountingFirm类、TaxBureau类、TradeBureau类是具体访问者(Concrete Visitor)角色。AbstractCompany抽象类是抽象节点(Node)角色。CompanyA类和CompanyB类是具体节点(Node)角色。其结构类图如图3所示。AccountingFirm类、TaxBureau类、TradeBureau类继承Visitor抽象类,CompanyA类和CompanyB类继承AbstractCompany抽象类。AbstractCompany抽象类关联Visitor抽象类。

Gof23种设计模式(23)——访问者模式(Visitor)图3 访问者模式类图

访问者模式实现顺序图见图4,实现顺序描述:
①基于CompanyA类创建一个company1对象;
②基于CompanyB类创建一个company2对象;
③基于AccountingFirm类创建一个accountingFirm对象;
④基于TaxBureau类创建一个taxBureau对象;
⑤基于TradeBureau类创建一个tradeBureau对象;
⑥调用company1对象的accept方法,把accountingFirm对象赋值给company1对象;
⑦调用company1对象的doVisit方法,显示参观内容;
⑧调用company1对象的accept方法,把taxBureau对象赋值给company1对象;
⑨调用company1对象的doVisit方法,显示参观内容;
⑩调用company1对象的accept方法,把tradeBureau对象赋值给company1对象;
(11)调用company1对象的doVisit方法,显示参观内容;
(12)调用company1对象的accept方法,把accountingFirm对象赋值给company1对象;
(13)调用company1对象的doVisit方法,显示参观内容。
(14)调用company2对象的accept方法,把taxBureau对象赋值给company1对象;
(15)调用company2对象的doVisit方法,显示参观内容。
(16)调用company2对象的accept方法,把tradeBureau对象赋值给company1对象;
(17)调用company2对象的doVisit方法,显示参观内容。

Gof23种设计模式(23)——访问者模式(Visitor)图4 访问者模式实现顺序图

3.Java的实现程序代码

Java程序实现主要包括Visitor抽象类文件,AbstractCompany抽象类文件,AccountingFirm类文件、TaxBureau类文件、TradeBureau类文件,CompanyA类文件和CompanyB类文件等7个文件。其关系如图3所示。下面分别列出这7个文件的程序代码,最后列出测试代码并显示输出结果。

Visitor类程序代码清单01所示。

程序代码清单01

public abstract class Visitor {

	public void visitCompanyA(CompanyA company) {
	}

	public void visitCompanyB(CompanyB company) {
	}

}

AbstractCompany抽象类程序代码清单02所示。

程序代码清单02

public abstract class AbstractCompany {

	protected Visitor vistor;

	public void accept(Visitor vistor) {
		this.vistor = vistor;
	}

	public void doVisit() {
	}

}

AccountingFirm类、TaxBureau类、TradeBureau类文件继承Visitor抽象类,其程序代码清单01所示。

程序代码清单03

public class AccountingFirm extends Visitor {

	public void visitCompanyA(CompanyA company) {
		System.out.println("对CompanyA类公司进行会计审计工作");
	}

	public void visitCompanyB(CompanyB company) {
		System.out.println("对CompanyB类公司进行会计审计工作");
	}
}

public class TaxBureau extends Visitor {

	public void visitCompanyA(CompanyA company) {
		System.out.println("对CompanyA类公司进行税务审计工作");
	}

	public void visitCompanyB(CompanyB company) {
		System.out.println("对CompanyB类公司进行税务审计工作");
	}

}

public class TradeBureau extends Visitor {

	public void visitCompanyA(CompanyA company) {
		System.out.println("对CompanyA类公司进行工商年审工作");
	}

	public void visitCompanyB(CompanyB company) {
		System.out.println("对CompanyB类公司进行工商年审工作");
	}
}

抽象公司的类程序代码清单01所示。

程序代码清单04

public class CompanyA extends AbstractCompany {

	public void visitA() {
	}

	public void doVisit() {
		vistor.visitCompanyA(this);
	}

}

public class CompanyB extends AbstractCompany {

	public void doVisit() {
		vistor.visitCompanyB(this);
	}

}

访问者模式测试程序的代码清单12如下:

程序代码清单05

public class Client {

	public static void main(String[] args) {

		AbstractCompany company1 = new CompanyA();
		AbstractCompany company2 = new CompanyB();

		Visitor accountingFirm = new AccountingFirm();
		Visitor taxBureau = new TaxBureau();
		Visitor tradeBureau = new TradeBureau();

		System.out.println("————对CompanyA类公司进行处理————");

		company1.accept(accountingFirm);
		company1.doVisit();
		company1.accept(taxBureau);
		company1.doVisit();
		company1.accept(tradeBureau);
		company1.doVisit();

		System.out.println("————对CompanyB类公司进行处理————");

		company2.accept(accountingFirm);
		company2.doVisit();
		company2.accept(taxBureau);
		company2.doVisit();
		company2.accept(tradeBureau);
		company2.doVisit();
	}
}

访问者模式测试类输出结果如下所示:

————对CompanyA类公司进行处理————
对CompanyA类公司进行会计审计工作
对CompanyA类公司进行税务审计工作
对CompanyA类公司进行工商年审工作

————对CompanyB类公司进行处理————
对CompanyB类公司进行会计审计工作
对CompanyB类公司进行税务审计工作
对CompanyB类公司进行工商年审工作

参考链接

11种行为型模式

Gof23种设计模式(13)——解释器模式(Interpreter)
Gof23种设计模式(14)——模板方法模式(Template Method)
Gof23种设计模式(15)——责任链模式(Chain of Responsibility)
Gof23种设计模式(16)——命令模式(Command)
Gof23种设计模式(17)——迭代器模式(Iterator)
Gof23种设计模式(18)——中介者模式(Mediator)
Gof23种设计模式(19)——备忘录模式(Memento)
Gof23种设计模式(20)——观察者模式(Observer)
Gof23种设计模式(21)——状态模式(State)
Gof23种设计模式(22)——策略模式(Strategy)
Gof23种设计模式(23)——访问者模式(Visitor)
Gof23种设计模式 —— 行为型模式总结和比较

回到总目录Gof23种设计模式(全解析)

(转载自微信公众号:架构设计模式)

素课网
  • 本文由 发表于 2020年8月14日10:25:57
  • 转载请注明:https://www.suketech.com/9287.html
设计模式:面向对象设计的六大原则 - 总结 设计模式

设计模式:面向对象设计的六大原则 – 总结

开闭原则是面向对象设计中最基础的设计原则,它指导我们如何建立稳定灵活的系统。开闭原则可能是设计模式六项原则中定义最模糊的一个了,它只告诉我们对扩展开放,对修改关闭,可是到底如何才能做到对扩展开放,对修...
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: