GoLang设计模式25 - 享元模式(结构型)
享元模式是什么
享元模式:是一种结构型设计模式,它允许你在消耗少量的内存的情况下支持大量的对象。享元模式通过共享多个对象的部分状态来实现上述功能。即是享元模式会将不同对象的相同功能缓存以节省内存。
为什么用享元模式
如果程序中有很多相似对象,这时候你就可以用享元模式来节约内存。
享元模式怎么实现
这里用dressFactorySingleInstance这个包常量来保存dress,用dressMap的key来对不同的dress分类。这个例子就是在这里达到共享的功能,因为无论多少玩家,而dress只有两类。所以无论多少玩家,dressFactorySingleInstance中的dress只有两个key,来达到dress共享。
dress_factory.go
package flyweight import "fmt" const ( TerroristDressType = "tDress" CounterTerroristDressType = "ctDress" ) type dressFactory struct { dressMap map[string]dress } var dressFactorySingleInstance = &dressFactory{ dressMap: make(map[string]dress,2), } func getDressFactorySingleInstance() *dressFactory { return dressFactorySingleInstance } func (d *dressFactory) getDressByType(dressType string) (dress, error) { if d.dressMap[dressType] != nil { return d.dressMap[dressType], nil } if dressType == TerroristDressType { d.dressMap[dressType] = newTerroristDress() return d.dressMap[dressType], nil } if dressType == CounterTerroristDressType { d.dressMap[dressType] = newCounterTerroristDress() return d.dressMap[dressType], nil } return nil, fmt.Errorf("Wrong dress type passed") }
dress.go
package flyweight type dress interface { getColor() string } type counterTerroristDress struct { color string } func (c *counterTerroristDress) getColor() string { return c.color } func newCounterTerroristDress() *counterTerroristDress { return &counterTerroristDress{color: "green"} } type terroristDress struct { color string } func (t *terroristDress) getColor() string { return t.color } func newTerroristDress() *terroristDress { return &terroristDress{color: "red"} }
game.go客户端代码
package flyweight type player struct { dress dress playerType string } func newPlayer(playerType, dressType string) *player { dress, _ := getDressFactorySingleInstance().getDressByType(dressType) return &player{ playerType: playerType, dress: dress, } } type game struct { terrorists []*player counterTerrorists []*player } func newGame() *game { return &game{ terrorists: make([]*player,0,1), counterTerrorists: make([]*player,0,1), } } func (c *game) addTerrorist(dressType string) { player := newPlayer("T", dressType) c.terrorists = append(c.terrorists, player) return } func (c *game) addCounterTerrorist(dressType string) { player := newPlayer("CT", dressType) c.counterTerrorists = append(c.counterTerrorists, player) return }
main.go客户端代码
func main() { game := newGame() //Add Terrorist game.addTerrorist(TerroristDressType) game.addTerrorist(TerroristDressType) //Add CounterTerrorist game.addCounterTerrorist(CounterTerroristDressType) game.addCounterTerrorist(CounterTerroristDressType) dressFactoryInstance := getDressFactorySingleInstance() for dressType, dress := range dressFactoryInstance.dressMap { fmt.Printf("DressColorType: %s\nDressColor: %s\n", dressType, dress.getColor()) } } // 结果: //DressColorType: tDress //DressColor: red //DressColorType: ctDress //DressColor: green
优点
- 如果程序中有很多相似对象, 那么你将可以节省大量内存。
缺点
- 代码会变得更加复杂。 团队中的新成员总是会问:“为什么要像这样拆分一个实体的状态?”。
- 你可能需要牺牲执行速度来换取内存,因为他人每次调用享元方法时都需要重新计算部分情景数据。
浙公网安备 33010602011771号