訪問者模式是什麼 訪問者是一種行為型設計模式, 允許你在不修改已有代碼的情況下向已有類層次結構中增加新的行為。 為什麼用訪問者模式 訪問者模式建議將新行為放入一個名為訪問者的獨立類中,而不是試圖將其整合到已有類中。現在需要執行操作的原始對象將作為參數被傳遞給訪問者中的方法, 讓方法能訪問對象所包含的 ...
訪問者模式是什麼
訪問者是一種行為型設計模式, 允許你在不修改已有代碼的情況下向已有類層次結構中增加新的行為。
為什麼用訪問者模式
訪問者模式建議將新行為放入一個名為訪問者的獨立類中,而不是試圖將其整合到已有類中。現在需要執行操作的原始對象將作為參數被傳遞給訪問者中的方法, 讓方法能訪問對象所包含的一切必要數據。當某個行為僅在類層次結構中的一些類中有意義,而在其他類中沒有意義時, 可使用該模式。
訪問者模式怎麼實現
這裡使用三個描述形狀的結構體舉例(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)
}
//運行結果:
//計算正方形的面積
//計算圓的面積
//計算矩形的面積
//計算正方形的中心坐標
//計算圓的中心坐標
//計算矩形的中心坐標
優點
- 開閉原則。 你可以引入在不同類對象上執行的新行為, 且無需對這些類做出修改。
- 單一職責原則。 可將同一行為的不同版本移到同一個類中。
缺點
- 增加新的元素類很困難。在訪問者模式中,每增加一個新的元素類,都要在每一個具體訪問者類中增加相應的具體操作,這違背了“開閉原則”。
- 破壞封裝。訪問者模式中具體元素對訪問者公佈細節,這破壞了對象的封裝性。
- 違反了依賴倒置原則。訪問者模式依賴了具體類,而沒有依賴抽象類。