结构型:七. 享元模式

享元模式是什么

享元模式:是一种结构型设计模式,它允许你在消耗少量的内存的情况下支持大量的对象。享元模式通过共享多个对象的部分状态来实现上述功能。即是享元模式会将不同对象的相同功能缓存以节省内存。

为什么用享元模式

如果程序中有很多相似对象,这时候你就可以用享元模式来节约内存。

享元模式怎么实现

这里用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

优点

  1. 如果程序中有很多相似对象, 那么你将可以节省大量内存。

缺点

  1. 代码会变得更加复杂。 团队中的新成员总是会问:“为什么要像这样拆分一个实体的状态?”。
  2. 你可能需要牺牲执行速度来换取内存,因为他人每次调用享元方法时都需要重新计算部分情景数据。

热门相关:斗神战帝   寂静王冠   刺客之王   最强装逼打脸系统   战神