訪問者模式是什么
訪問者是一種行為型設計模式, 允許你在不修改已有代碼的情況下向已有類層次結構中增加新的行為,
為什么用訪問者模式
訪問者模式建議將新行為放入一個名為訪問者的獨立類中,而不是試圖將其整合到已有類中,現在需要執行操作的原始物件將作為引數被傳遞給訪問者中的方法, 讓方法能訪問物件所包含的一切必要資料,當某個行為僅在類層次結構中的一些類中有意義,而在其他類中沒有意義時, 可使用該模式,
訪問者模式怎么實作
這里使用三個描述形狀的結構體舉例(circle,square,rectangle),而計算它們的中心點和面積的方法采用了訪問者的方式,這里的accept方法是改變了原有的封裝,但這樣的改變只會有一次,如果加入多個行為accept也只有一個即可,
shape.go
package visitor
type shape interface {
getType() string
accept(visitor)
}
circle.go
package visitor
type circle struct {
radius int
}
func (c *circle) accept(v visitor) {
v.visitForCircle(c)
}
func (c *circle) getType() string {
return "Circle"
}
square.go
package visitor
type square struct {
side int
}
func (s *square) accept(v visitor) {
v.visitForSquare(s)
}
func (s *square) getType() string {
return "Square"
}
rectangle.go
package visitor
type rectangle struct {
l int
b int
}
func (t *rectangle) accept(v visitor) {
v.visitForRectangle(t)
}
func (t *rectangle) getType() string {
return "rectangle"
}
visitor.go
package visitor
type visitor interface {
visitForSquare(*square)
visitForCircle(*circle)
visitForRectangle(*rectangle)
}
area_calculator.go
package visitor
import (
"fmt"
"math"
)
type areaCalculator struct {
area int
}
func (a *areaCalculator) visitForSquare(s *square) {
a.area = s.side * s.side
fmt.Println("計算正方形的面積")
}
func (a *areaCalculator) visitForCircle(s *circle) {
a.area = int(math.Pi * float64(s.radius * s.radius))
fmt.Println("計算圓的面積")
}
func (a *areaCalculator) visitForRectangle(s *rectangle) {
a.area = s.l * s.b
fmt.Println("計算矩形的面積")
}
middle_coordinates.go
package visitor
import "fmt"
type middleCoordinates struct {
x int
y int
}
func (a *middleCoordinates) visitForSquare(s *square) {
a.x = s.side / 2
a.y = s.side / 2
fmt.Println("計算正方形的中心坐標")
}
func (a *middleCoordinates) visitForCircle(c *circle) {
a.x = c.radius
a.y = c.radius
fmt.Println("計算圓的中心坐標")
}
func (a *middleCoordinates) visitForRectangle(t *rectangle) {
a.x = t.b / 2
a.y = t.l / 2
fmt.Println("計算矩形的中心坐標")
}
example.go客戶端呼叫示例
package visitor
func Example() {
square := &square{side: 2}
circle := &circle{radius: 3}
rectangle := &rectangle{l: 2, b: 3}
areaCalculator := &areaCalculator{}
square.accept(areaCalculator)
circle.accept(areaCalculator)
rectangle.accept(areaCalculator)
middleCoordinates := &middleCoordinates{}
square.accept(middleCoordinates)
circle.accept(middleCoordinates)
rectangle.accept(middleCoordinates)
}
//運行結果:
//計算正方形的面積
//計算圓的面積
//計算矩形的面積
//計算正方形的中心坐標
//計算圓的中心坐標
//計算矩形的中心坐標
優點
- 開閉原則, 你可以引入在不同類物件上執行的新行為, 且無需對這些類做出修改,
- 單一職責原則, 可將同一行為的不同版本移到同一個類中,
缺點
- 增加新的元素類很困難,在訪問者模式中,每增加一個新的元素類,都要在每一個具體訪問者類中增加相應的具體操作,這違背了“開閉原則”,
- 破壞封裝,訪問者模式中具體元素對訪問者公布細節,這破壞了物件的封裝性,
- 違反了依賴倒置原則,訪問者模式依賴了具體類,而沒有依賴抽象類,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/464092.html
標籤:其他
上一篇:系統設計的11個考慮
下一篇:行為型:十一. 解釋器模式
