文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Go设计模式--访客模式

2024-11-30 16:30

关注

访客模式也叫访问者模式(Visitor Pattern)是一种将数据结构对象与数据操作分离的设计模式,可以在不改变数据结构对象类结构的前提下定义作用于这些对象的新的操作, 属于行为型设计模式。

访问者模式主要适用于以下应用场景:

  1. 数据结构稳定,作用于数据结构的操作经常变化的场景。
  2. 需要数据结构与数据操作分离的场景。
  3. 需要对不同数据类型(元素)进行操作,而不使用分支判断具体类型的场景。

访客模式怎么工作?

访问者模式通过将算法与对象结构分离来工作,这里说的算法指的是对对象的操作。为此,我们需要定义了一个表示算法的接口--Visitor。该接口将为对象结构中的每个类(一般称为元素类)提供一个方法。每个方法都将元素类的一个实例作为参数。表示对象结构的所有元素类也会实现一个Element接口,该接口定义了接受访问者的方法Accpet。此方法将访问者接口的实现作为参数。当Accpet方法被调用时,访问者实例对应的方法就会被调用,通过访问者完成对元素类实例的操作。

下面我们看一下访问者模式的类结构。

访客模式结构

访问者的类结构可以用下面的UML类图来表示:

访客模式代码示例

在这个用访客模式实现不同维度的订单统计的例子里,假设我们建设了一个订单管理系统, 现在系统中要求能按照不同维度统计分析销售订单

以后还有可能增加其他维度的销售统计报表,针对这个需求我们可以根据访问者模式, 可将不同的报表, 设计为订单的访问者。 首先定义订单实体和它要实现的Element接口

"本文使用的完整可运行源码
去公众号「网管叨bi叨」发送【设计模式】即可领取"
// 订单服务接口
type IOrderService interface {
Save(order *Order) error
// 有的教程里把接收 visitor 实现的方法名定义成 Accept
Accept(visitor IOrderVisitor)
}


// 订单实体类,实现IOrderService 接口
type Order struct {
ID int
Customer string
City string
Product string
Quantity int
}

func (mo *OrderService) Save(o *Order) error {
mo.orders[o.ID] = o
return nil
}

func (mo *OrderService) Accept(visitor IOrderVisitor) {
for _, v := range mo.orders {
visitor.Visit(v)
}
}

func NewOrder(id int, customer string, city string, product string, quantity int) *Order {
return &Order{
id, customer,city,product,quantity,
}
}

接下来定义生成各种销售报表的访客类,以及它们实现的访客接口

"本文使用的完整可运行源码
去公众号「网管叨bi叨」发送【设计模式】即可领取"
type IOrderVisitor interface {
// 这里参数不能定义成 IOrderService
Visit(order *Order)
Report()
}

type CityVisitor struct {
cities map[string]int
}

func (cv *CityVisitor) Visit(o *Order) {
n, ok := cv.cities[o.City]
if ok {
cv.cities[o.City] = n + o.Quantity
} else {
cv.cities[o.City] = o.Quantity
}
}

func (cv *CityVisitor) Report() {
for k,v := range cv.cities {
fmt.Printf("city=%s, sum=%v\n", k, v)
}
}

func NewCityVisitor() IOrderVisitor {
return &CityVisitor{
cities: make(map[string]int, 0),
}
}

// 品类销售报表, 按产品汇总销售情况, 实现ISaleOrderVisitor接口
type ProductVisitor struct {
products map[string]int
}

func (pv *ProductVisitor) Visit(it *Order) {
n,ok := pv.products[it.Product]
if ok {
pv.products[it.Product] = n + it.Quantity
} else {
pv.products[it.Product] = it.Quantity
}
}

func (pv *ProductVisitor) Report() {
for k,v := range pv.products {
fmt.Printf("product=%s, sum=%v\n", k, v)
}
}

func NewProductVisitor() IOrderVisitor {
return &ProductVisitor{
products: make(map[string]int,0),
}
}

最后我们尝试使用Vistor生成各种销售报表

func main() {
orderService := NewOrderService()
orderService.Save(NewOrder(1, "张三", "广州", "电视", 10))
orderService.Save(NewOrder(2, "李四", "深圳", "冰箱", 20))
orderService.Save(NewOrder(3, "王五", "东莞", "空调", 30))
orderService.Save(NewOrder(4, "张三三", "广州", "空调", 10))
orderService.Save(NewOrder(5, "李四四", "深圳", "电视", 20))
orderService.Save(NewOrder(6, "王五五", "东莞", "冰箱", 30))

cv := NewCityVisitor()
orderService.Accept(cv)
cv.Report()

pv := NewProductVisitor()
orderService.Accept(pv)
pv.Report()
}


来源:网管叨bi叨内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯