我有點新手并且在運行和界面上有一個架構問題:我需要存盤有關車輛的資訊并假設它可能是汽車、公共汽車、救護車、救火車等。所以車輛是介面,每個確切的車輛型別都是結構,但所有這些有一些共同的領域(顏色,車輪數量,座椅,消音器等),當我需要一些共同的東西時,我可以采取以下方式:
- 根本不使用介面,并且每次都檢查一個包含大量 getter 和 setter 的大結構“如果車輛型別 X 可以具有欄位 Z?”。它使這些方法非常難以閱讀并且很容易忘記檢查smthng。
- 每次對每種型別執行型別斷言以獲取確切的欄位。因此,為了獲得顏色,我需要為 10 行撰寫型別開關。
- 為每個公共欄位添加到介面 getter:
type Vehicle interface {
Colour() string
Wheels() int
Seats() int
Mufflers() int
...
}
正如我所見,它是“保持介面小”的反模式,并且會產生很多非常相似的代碼(每個結構都使用相同的方法)
- 有一些像 CommonVehicle 這樣的結構,它存盤所有公共欄位和所有其他車輛型別嵌入它,并且介面只有方法回傳這個 CommonVehicle:
type Vehicle interface {
Common() CommonVehicle
}
type CommonVehicle struct {
// common fields
}
type Car struct {
CommonVehicle
// uncommon fields
}
// implementation for Vehicle interface
當我需要獲取顏色時,我會使用 vehicle.Common().Colour。它在介面和型別方面看起來很清楚,但它可能會誤導每次呼叫 Common 以從 Vehicle 中獲取任何東西。
對此的最佳做法是什么?也許我錯過了一些東西,需要走其他路?
uj5u.com熱心網友回復:
您正在嘗試使用Go 中不支持的繼承(并且有些人認為這總體上不是一個好的模式)。相反,您應該使用組合(這正是您的#4 選項所建議的)。
這篇博文完美地描述了它
作為一般設計規則的不同方法
而不是試圖定義物件的介面,你應該瞄準你希望你的物件能夠做到的能力。這與您的問題沒有 100% 的關聯,但它有助于維護小型介面的模式。
讓我們以汽車為例:我們可以用汽車做什么?
- 駕駛它
- 也許聽音樂
- 賣掉它
- 驚嘆于它的美麗
既然我們知道我們可以用車輛做什么,我們應該將這些動作中的每一個作為它自己的界面。 為什么?- 因為它允許對任何車輛物體進行最精細的描述,而無需對車輛的具體實作進行任何假設。
所以我們有以下介面:
type Drivable interface{ Drive(float64, float64) } // drive to a latitude, longitude quordinate
type Listenable interface{ Listen() []byte } // Listen return a stream of bytes as the audio output
type Sellable interface { Sell(float64, string) } // sell for X amount of money to some person
type Describable interface { Describe() string }
現在有了這 4 個介面,我們可以創建我們想要的任何型別的車輛:
- 有些車輛沒有收音機,所以他們可能不應該實作這個
Listenable介面。 - 有些車輛是警車 - 城市擁有它們 - 所以它們并不真正可售
- 等等等等……
關鍵是要有不同的能力,我們應該從這些能力中建立我們的物體——反之亦然。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/443014.html
上一篇:Golang-創建結構陣列?
下一篇:接收未定義而不是JSON
