访问者模式

定义

wiki: 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

平时我们定义完一个类之后,这个类所能执行的逻辑就是确定的了,但是我们经常会遇到一种场景: 根据外部环境更改这个类所能执行的行为。

访问者模式 就是在不更改这个类的前提下,更改这个类中方法所能执行的逻辑。

角色组成

  • 抽象访问者
  • 访问者
  • 抽象元素类
  • 元素类
  • 结构容器: (非必须) 保存元素列表,可以放置访问者

类图


(图源网络)

大概的流程就是:

  1. 从结构容器中取出元素
  2. 创建一个访问者
  3. 将访问者载入传入的元素(即让访问者访问元素)
  4. 获取输出

举个栗子

例如,一个对象的方法,在测试环境要打印出: 这是测试环境,在生产环境中要打印出: 这是生产环境

一般最开始会这样写:

Print()
Print()Print()

一个函数的实现是十分复杂的,有可能更改了这个方法,会导致整个系统崩溃,所以解耦是一个十分迫切的需要.

MapList
  1. 定义访问者接口
// 定义访问者接口    
type IVisitor interface {
     Visit() // 访问者的访问方法    
}
  1. 实现该接口


  1. 创建元素接口
// 定义元素接口     
type IElement interface {
         Accept(visitor IVisitor)
     }


4. 实现元素接口


Print()

6. 开始调用


自从各个语言开始支持匿名函数之后,访问者模式就变得极其简单了,每一种传入匿名方法的操作都可以看做是变相的访问者模式, golang 中的方法也是一种类型的对象,所以可以用它便利的实现访问者模式,下面看一个实际栗子

看一个实际应用的栗子

生产环境测试环境本地环境预发布环境ORM
LaravelBlueprint
BlueprintSchema::create()phpgo
README
test
CreateTable
sqlSQLIBlueprintIBlueprint

这对我们的开发包扩展提供了极大的方便。

如果想练手,可以 fork 一下这个项目,然后实现一下各种数据库的访问(我现在正在写mysql,并且还没有实现完全),并提 PR 给我喔~

具体内容可以去看源码,这个包里的注释我写了不少...

ORM