1 回答
TA贡献1820条经验 获得超2个赞
这似乎是一个关于如何设计项目中的数据结构和操作及其依赖关系的一般软件工程问题。
正如您所发现的,循环导入是不好的。有很多方法可以改变设计来解耦事物。一个是清晰的层——例如,Bank
应该依赖Human
而不是相反。但是,如果您想提供方便的功能来将钱从 转移Human
到Human
,您可以做的一件事是定义一个Bank
对象将实现的接口。
然而,为简单起见,我建议严格分层。没有真正的理由 aHuman
应该依赖于 a Bank
。在极限情况下,这可能会变得太麻烦,因为Human
s 需要更多服务(你会依赖Human
aBus
来让Bus
es 移动Human
s 吗?)
为了回答评论和更新的问题,我会保持简单:
package main
import (
"fmt"
"log"
)
type Human struct {
ID int64
Name string
}
type Account struct {
ID int64
// Note: floats aren't great for representing money as they can lose precision
// in some cases. Keeping this for consistency with original.
Cash float64
DaysSinceActive int64
}
type Bank struct {
Accounts map[int64]Account
}
// Not checking negatives, etc. Don't use this for real banking :-)
func (bank *Bank) Transfer(src int64, dest int64, sum float64) error {
srcAcct, ok := bank.Accounts[src]
if !ok {
return fmt.Errorf("source account %d not found", src)
}
destAcct, ok := bank.Accounts[dest]
if !ok {
return fmt.Errorf("destination account %d not found", dest)
}
// bank.Accounts[src] fetches a copy of the struct, so we have to assign it
// back after modifying it.
srcAcct.Cash -= sum
bank.Accounts[src] = srcAcct
destAcct.Cash += sum
bank.Accounts[dest] = destAcct
return nil
}
func main() {
gary := Human{19928, "Gary"}
sam := Human{99555, "Sam"}
bank := Bank{Accounts: map[int64]Account{}}
bank.Accounts[gary.ID] = Account{gary.ID, 250.0, 10}
bank.Accounts[sam.ID] = Account{sam.ID, 175.0, 5}
fmt.Println("before transfer", bank)
if err := bank.Transfer(gary.ID, sam.ID, 25.0); err != nil {
log.Fatal(err)
}
fmt.Println("after transfer", bank)
}
这段代码使用了松散耦合。银行需要知道的关于一个人的所有信息就是他们的 ID(可以是 SSN 或根据姓名、出生日期和其他内容计算出来的东西)来唯一地识别他们。人类应该持有银行(如果一个人在多家银行都有账户怎么办?)。银行不应该持有人(如果账户属于多个人、公司、虚拟实体怎么办?)等等。这里不需要接口,如果确实需要,您可以安全地将每种数据类型放在它们自己的包中。
- 1 回答
- 0 关注
- 124 浏览
添加回答
举报