访问者模式(Visitor)

访问者模式(Visitor)

1.意图

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

2.适用性

在下列情况下使用Visitor模式:

  • 一个对象结构包含很多类对象,它们有不同的接口,而你想对这些对象实施一些依赖于其具体类的操作。
  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而你想避免让这些操作“污染”这些对象的类。Visitor使得你可以将相关的操作集中起来定义在一个类中。当该对象结构被很多应用共享时,用Visitor模式让每个应用仅包含需要用到的操作。
  • 定义对象结构的类很少改变,但经常需要在此结构上定义新的操作。改变对象结构类需要重定义对所有访问者的接口,这可能需要很大的代价。如果对象结构类经常改变,那么可能还是在这些类中定义这些操作较好。
3.结构

在这里插入图片描述

4.代码
package visitor

import "testing"

/*
# 访问者模式
访问者模式可以给一系列对象透明的添加功能,并且把相关代码封装到一个类中。
对象只要预留访问者接口`Accept`则后期为对象添加功能的时候就不需要改动对象。
*/

type Visitor interface {
	VisitCPU(cpu CPU)
	VisitMemory(memory Memory)
	VisitBoard(board Board)
}


type ComputerPart interface {
	Accept(visitor Visitor)
	//some other operations eg:getName getBrand
	GetPrice()float64
}


type CPU struct {
	ComputerPart
}

func (this CPU)Accept(visitor Visitor){
	visitor.VisitCPU(this)
}
func (this CPU)GetPrice()float64{
	return 500
}


type Memory struct {
	ComputerPart
}

func (this Memory)Accept(visitor Visitor){
	visitor.VisitMemory(this)
}
func (this Memory)GetPrice()float64{
	return 300
}

type Board struct {
	ComputerPart
}

func (this Board)Accept(visitor Visitor){
	visitor.VisitBoard(this)
}
func (this Board)GetPrice()float64{
	return 200
}


type Computer struct {
	cpu    CPU
	memory Memory
	board  Board
}

func (this *Computer)Accept(visitor Visitor){
	this.cpu.Accept(visitor)
	this.memory.Accept(visitor)
	this.board.Accept(visitor)
}

type PersonelVisitor struct {
	TotalPrice float64
	Visitor
}

func (this *PersonelVisitor)VisitCPU(cpu CPU)  {
	this.TotalPrice += cpu.GetPrice()*0.9

}
func (this *PersonelVisitor)VisitMemory(memory Memory)  {
	this.TotalPrice += memory.GetPrice()*0.85
}
func (this *PersonelVisitor)VisitBoard(board Board)  {
	this.TotalPrice += board.GetPrice()*0.9
}

type CorpVisitor struct {
	TotalPrice float64
	Visitor
}
func (this *CorpVisitor)VisitCPU(cpu CPU)  {
	this.TotalPrice += cpu.GetPrice()*0.6
}
func (this *CorpVisitor)VisitMemory(memory Memory)  {
	this.TotalPrice += memory.GetPrice()*0.75
}
func (this *CorpVisitor)VisitBoard(board Board)  {
	this.TotalPrice += board.GetPrice()*0.75
}

func TestVisitor(t *testing.T)  {
	p0:=&PersonelVisitor{}
	p1:=&CorpVisitor{}
	c:=Computer{}
	c.Accept(p0)
	c.Accept(p1)


	t.Log("Personel购买价格:",p0.TotalPrice)
	t.Log("Corp购买价格:",    p1.TotalPrice)
}



//type Customer interface {
//	Accept(Visitor)
//}
//
//type Visitor interface {
//	Visit(Customer)
//}
//
//
//type EnterpriseCustomer struct {
//	name string
//}
//
//type CustomerCol struct {
//	customers []Customer
//}
//
//func (c *CustomerCol) Add(customer Customer) {
//	c.customers = append(c.customers, customer)
//}
//
//func (c *CustomerCol) Accept(visitor Visitor) {
//	for _, customer := range c.customers {
//		customer.Accept(visitor)
//	}
//}
//
//func NewEnterpriseCustomer(name string) *EnterpriseCustomer {
//	return &EnterpriseCustomer{
//		name: name,
//	}
//}
//
//func (c *EnterpriseCustomer) Accept(visitor Visitor) {
//	visitor.Visit(c)
//}
//
//type IndividualCustomer struct {
//	name string
//}
//
//func NewIndividualCustomer(name string) *IndividualCustomer {
//	return &IndividualCustomer{
//		name: name,
//	}
//}
//
//func (c *IndividualCustomer) Accept(visitor Visitor) {
//	visitor.Visit(c)
//}
//
//type ServiceRequestVisitor struct{}
//
//func (*ServiceRequestVisitor) Visit(customer Customer) {
//	switch c := customer.(type) {
//	case *EnterpriseCustomer:
//		fmt.Printf("serving enterprise customer %s\n", c.name)
//	case *IndividualCustomer:
//		fmt.Printf("serving individual customer %s\n", c.name)
//	}
//}
//
 only for enterprise
//type AnalysisVisitor struct{}
//
//func (*AnalysisVisitor) Visit(customer Customer) {
//	switch c := customer.(type) {
//	case *EnterpriseCustomer:
//		fmt.Printf("analysis enterprise customer %s\n", c.name)
//	}
//}
//
//
//func ExampleRequestVisitor() {
//	c := &CustomerCol{}
//	c.Add(NewEnterpriseCustomer("A company"))
//	c.Add(NewEnterpriseCustomer("B company"))
//	c.Add(NewIndividualCustomer("bob"))
//	c.Accept(&ServiceRequestVisitor{})
//	// Output:
//	// serving enterprise customer A company
//	// serving enterprise customer B company
//	// serving individual customer bob
//}
//
//func ExampleAnalysis() {
//	c := &CustomerCol{}
//	c.Add(NewEnterpriseCustomer("A company"))
//	c.Add(NewIndividualCustomer("bob"))
//	c.Add(NewEnterpriseCustomer("B company"))
//	c.Accept(&AnalysisVisitor{})
//	// Output:
//	// analysis enterprise customer A company
//	// analysis enterprise customer B company
//}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

metabit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值