访问者模式
访问者模式(Visitor Pattern)是 行为型设计模式 之一,它允许你在不修改对象结构的前提下(在此模式下,通常是不需要修改数据结构的场景),为对象结构中的元素定义新的操作。换句话说,它将“数据结构”与“作用于数据结构上的操作”分离,使得可以在不改变这些元素类的情况下增加新的操作。也可以理解为,同一数据结构在不同场景下执行不同操作。
核心思想
- 将算法与对象结构分离。
- 通过“双重分派”实现动态绑定。
- 新增操作时,只需添加一个新的访问者,而无需修改已有类。
角色组成
Visitor(抽象访问者) 定义对每个具体元素(Element)访问的操作接口,如
visit(ElementA)、visit(ElementB)。ConcreteVisitor(具体访问者) 实现抽象访问者中定义的操作,即具体的业务逻辑(如打印、统计、计算等)。
Element(抽象元素) 定义一个
accept(Visitor visitor)方法,表示接受访问者访问。ConcreteElement(具体元素) 实现
accept()方法,通常调用访问者的visit(this)方法。ObjectStructure(对象结构) 可以是集合、组合结构等,能够枚举其中的元素,并提供一个高层接口让访问者访问所有元素
代码实现:
typescript
//定义元素抽象类
abstract class IElement {
public name: string
//实现该接口的类必须实现一个accept方法
abstract accept(visit: Visitor): void
}
//构建固定的角色类<前端开发>
class FrontendDevelopment implements IElement {
public name: string = 'FrontendDevelopment'
public accept(visitor: Visitor) {
visitor.visitFrontEnd(this)
}
}
//构建固定的角色类<后端开发>
class BackendDevelopment implements IElement {
public name: string = 'backendDevelopment'
public accept(visitor: Visitor): void {
visitor.visitBackEnd(this)
}
}
//定义visitor的抽象接口
abstract class Visitor {
abstract visitFrontEnd(frontend: FrontendDevelopment): void
abstract visitBackEnd(backend: BackendDevelopment): void
}
//实现一个软件开发公司类
class SoftwareCompany {
private members = [] as (FrontendDevelopment | BackendDevelopment)[]
constructor() {
this.members.push(new FrontendDevelopment())
this.members.push(new BackendDevelopment())
}
public startProject(visitor: Visitor) {
this.members.forEach((i) => i.accept(visitor))
}
}
//实现具体的访问者类
class WechaApp implements Visitor {
visitFrontEnd(frontend: FrontendDevelopment): void {
console.log(`[ ${frontend.name} ] >`, `在仿微信小程序做前端开发任务`)
}
visitBackEnd(backend: BackendDevelopment): void {
console.log(`[ ${backend.name} ] >`, `在仿微信小程序做后端开发任务`)
}
}
class GameApp implements Visitor {
visitFrontEnd(frontend: FrontendDevelopment): void {
console.log(`[ ${frontend.name} ] >`, `在仿游戏app开发做前端开发任务`)
}
visitBackEnd(backend: BackendDevelopment): void {
console.log(`[ ${backend.name} ] >`, `在仿游戏开发app做后端端开发任务`)
}
}
const company = new SoftwareCompany()
company.startProject(new WechaApp())
company.startProject(new GameApp())