3 回答
TA贡献1812条经验 获得超5个赞
使用第三个套餐选项:
yourgame/
state/
state.go
modifier/
modifier.go
main.go
main.go 将两个组件粘合在一起:
import "yourgame/state"
import "yourgame/modifier"
type Game struct {
state state.State
modifier modifier.Modifier
}
func main() {
// something like:
var game Game
game.modifier.Modify(game.state)
}
不过,这种方法可能过于紧密耦合。与其操作本质上是全局的状态对象,不如尝试将数据分割成修改器所需的数据。
抽象的推理很难,所以这里有一个具体的例子来说明我的意思。在你的游戏中:
type Object struct {
ID, X, Y int
// more data here
}
type Game struct {
Objects map[int]*Object
}
在您的“修改器”中,假设我们有一个移动对象的 AI 模块。如果他只关心单个对象的位置,您可以创建一个界面:
// in yourgame/modifier
type Object interface {
GetCoordinates() (int, int)
SetCoordinates(int, int)
}
type Modifier struct {}
func (m *Modifier) Update(obj Object) { }
然后我们只需要将这些方法添加到我们的原始对象中:
type (obj *Object) GetCoordinates() (int, int) {
return obj.X, obj.Y
}
type (obj *Object) SetCoordinates(x, y int) {
obj.X, obj.Y = x, y
}
现在您可以将对象传递给您的修改器,而无需循环依赖。
现在,如果事实证明您的“修改器”界面最终看起来与您的游戏对象几乎完全相同,那么第三个结构包可能是合理的,因此您不必总是重复自己。例如,考虑net/url.
TA贡献1773条经验 获得超3个赞
通常,如果 packageB有直接读取/修改的代码,A.Type那么该代码应该在 package 中A。至少需要直接访问的部分应该是。
要在单独的包之间拆分某些内容A,B您通常会尝试隔离 API 以访问A.Type可以表示为接口的 API 。然后B将定义和使用这个接口并A.Type实现它(隐式地,不需要包含 B 对它的定义)。
然后一些东西(可能A,可能是一个单独的包)将B通过适当地传递一个A.Type或*A.Type值来使用。
或者,根据您的设计,这种关系可以颠倒,B.OtherType隐式实现由A. 或两者A并B只能通过接口使用对方; 这一切都取决于细节。
例如,也许是这样的:
package Game // "A"
type State struct {
data int // etc
}
func (s State) IsValid() bool { return true }
func (s *State) ChangeY(arg int) error { return nil }
// …etc…
和:
package Modifier // "B"
type GameState interface {
IsValid() bool
ChangeY(int) error
}
type M struct {
s GameState
//…
}
func New(s GameState) *M {
return &M{s: s}
}
func (m M) DoSomething() {
if s.IsValid() {
// …
}
s.ChangeY(42)
// …etc…
}
TA贡献1963条经验 获得超6个赞
我会在同一个包中定义类型(在这种情况下是游戏)及其所有方法。你甚至不能根据语言规范定义从另一个包导入的类型的方法,
//you should first do
type MyPackageType ImportedType
//and only then
func (foo MyPackageType) Modify() {
...
}
- 3 回答
- 0 关注
- 180 浏览
添加回答
举报