享元模式(Flyweight Pattern)是一种结构型设计模式,用于有效地支持大量细粒度对象的共享。享元模式通过共享对象的方式来减少内存使用和提高性能。
享元模式的实现代码
package main
import (
"fmt"
"sync"
)
/*
业务场景描述:
- 租车场景,客户像车行租车,如果车行有车直接租给客户,没有则从车行的其他分部调车分配
场景角色:
- 1.抽象享元,接口,实现产品具有属性
- 2.具体享元,类,实现抽象享元
- 3.享元工厂,控制和管理享元
- 4.客户端,请求获取产品
*/
// 1.抽象享元-便于扩展
type iFlyweight interface {
drive()
}
// 2.具体享元
type flyweight struct {
name string
}
func NewFlyweight(name string) *flyweight {
return &flyweight{
name: name,
}
}
func (r *flyweight) drive() {
fmt.Printf("the car [%s] is driving on the road.\n", r.name)
}
// 3.享元工厂
type flyweightFactory struct {
pool map[string]*flyweight
}
func NewFlyweightFactory() *flyweightFactory {
return &flyweightFactory{
pool: make(map[string]*flyweight),
}
}
func (r *flyweightFactory) Get(name string) *flyweight {
object, ok := r.pool[name]
if !ok {
object = r.schedule(name)
r.pool[name] = object
}
return object
}
// 相当于新建对象
func (r *flyweightFactory) schedule(name string) *flyweight {
fmt.Printf("车行从其他分部调入: [%s]\n", name)
return &flyweight{name}
}
// 用完之后的还车
func (r *flyweightFactory ) Put(object *flyweight) error {
r.pool[object.name] = object
return nil
}
// sync.pool 实现,封装更好,直接get、put即可
type flyweightFactoryV2 struct {
pool sync.Pool
}
func NewFlyweightFactoryV2() *flyweightFactoryV2 {
factory := &flyweightFactoryV2{}
factory.pool.New = func() any {
return new(flyweight)
}
return factory
}
func (r *flyweightFactoryV2) Get(name string) *flyweight {
// 使用时需要断言
object := r.pool.Get().(*flyweight)
return r.warp(name, object)
}
func (r *flyweightFactoryV2) warp(name string, fly *flyweight) *flyweight {
fmt.Printf("正在租出一辆车: [%s]\n", name)
fly.name = name
return fly
}
// 用完之后的还车
func (r *flyweightFactoryV2) Put(object *flyweight) error {
r.pool.Put(object)
return nil
}
// 4.客户端
func main() {
// map实现共享池
fac := NewFlyweightFactory()
// 获取对象
car := fac.Get("BMW")
// 使用对象
car.drive()
// 用完还车
_ = fac.Put(car)
// 再次租车
car1 := fac.Get("BMW")
// 租其他车
car2 := fac.Get("Benz")
// 直接还车
fac.Put(car1)
fac.Put(car2)
/* result:
车行从其他分部调入: [BMW]
the car [BMW] can driving on the road.
车行从其他分部调入: [Benz]
*/
// sync.Pool实现共享池
facV2 := NewFlyweightFactoryV2()
// rent
car3 := facV2.Get("RR")
// use
car3.drive()
// return car
facV2.Put(car3)
}
终端输出
享元模式的代码拆分
1.项目的准备工作
找到 go 的 GOPATH
$ go env //可以查看 GOPATH
在 GOPATH 目录下创建3个文件夹
1.bin文件夹 -- 存放编译后的二进制文件
2.pkg文件夹 -- 存放编译后的库文件
3.src文件夹 -- 存放源码文件
2.创建文件夹
// -- 在项目文件夹 flyweight_case 里创建新文件夹
// flyweight -- 存放装饰者的全部文件
3.接口文件 -- flyweight文件夹
文件1 -- iflyweight.go
package flyweight
// 抽象享元-便于扩展
type iFlyweight interface {
Drive()
}
4.结构体文件 -- flyweight文件夹
文件1 -- flyweight.go
package flyweight
import "fmt"
// 具体享元
type flyweight struct {
name string
}
// 创建享元
func NewFlyweight(name string) *flyweight {
return &flyweight{
name: name,
}
}
// 汽车在行驶
func (r *flyweight) Drive() {
fmt.Printf("the car [%s] is driving on the road.\n", r.name)
}
文件2 -- fwfactory.go
package flyweight
import "fmt"
// 享元工厂
type flyweightFactory struct {
pool map[string]*flyweight
}
// 新建享元工厂
func NewFlyweightFactory() *flyweightFactory {
return &flyweightFactory{
pool: make(map[string]*flyweight),
}
}
// 根据名字获取汽车
func (r *flyweightFactory) Get(name string) *flyweight {
object, ok := r.pool[name]
if !ok { //如果该汽车不存在,就从其他分部调入
object = r.schedule(name)
r.pool[name] = object
}
return object
}
// 相当于新建对象
func (r *flyweightFactory) schedule(name string) *flyweight {
fmt.Printf("车行从其他分部调入: [%s]\n", name)
return &flyweight{name}
}
// 用完之后的还车
func (r *flyweightFactory ) Put(object *flyweight) error {
r.pool[object.name] = object
return nil
}
文件3 -- fwfactoryv2.go
package flyweight
import (
"fmt"
"sync"
)
// sync.pool 实现,封装更好,直接get、put即可
type flyweightFactoryV2 struct {
pool sync.Pool
}
func NewFlyweightFactoryV2() *flyweightFactoryV2 {
factory := &flyweightFactoryV2{}
factory.pool.New = func() any { // any 为空接口
return new(flyweight)
}
return factory
}
// 租车
func (r *flyweightFactoryV2) Get(name string) *flyweight {
// 使用时需要断言
object := r.pool.Get().(*flyweight)
// 租车并且返回该车
return r.warp(name, object)
}
func (r *flyweightFactoryV2) warp(name string, fly *flyweight) *flyweight {
fmt.Printf("正在租出一辆车: [%s]\n", name)
fly.name = name
return fly
}
// 用完之后的还车
func (r *flyweightFactoryV2) Put(object *flyweight) error {
r.pool.Put(object)
return nil
}
5.主文件 -- main.go 在项目文件夹
package main
import (
"design/flyweight_case/flyweight"
)
// 客户端
func main() {
// map实现共享池
fac := flyweight.NewFlyweightFactory()
// 获取对象
car := fac.Get("BMW")
// 使用对象
car.Drive()
// 用完还车
_ = fac.Put(car)
// 再次租车
car1 := fac.Get("BMW")
// 租其他车
car2 := fac.Get("Benz")
// 直接还车
fac.Put(car1)
fac.Put(car2)
/* result:
车行从其他分部调入: [BMW]
the car [BMW] can driving on the road.
车行从其他分部调入: [Benz]
*/
// sync.Pool实现共享池
facV2 := flyweight.NewFlyweightFactoryV2()
// rent
car3 := facV2.Get("RR")
// use
car3.Drive()
// return car
facV2.Put(car3)
}