这次介绍最后一个创建型模式——对象池模式。顾名思义,对象池模式就是预先初始化创建好多个对象,并将之保存在一个池子里。当需要的时候,客户端就可以从池子里申请一个对象使用,使用完以后再将之放回到池子里。池子里的对象在应用运行期间永远不会被破坏或回收。
适用场景:
我们在开发中最熟悉的对象池应该是数据库连接池了。因为网络因素,数据库连接池中的每个对象的创建成本都比较高,且应用在运行期间会需要多个数据库连接对象。另外,每个数据库的连接池中对象的属性都是一样的,且在运行期间这些对象的属性几乎通常都是不可变的。
来看个模拟的数据库连接对象池模型的例子。
iPoolObject.go
type iPoolObject interface {
	//This is any id which can be used to compare two different pool objects
	getID() string
}
connection.go
type connection struct {
	id string
}
func (c *connection) getID() string {
	return c.id
}
pool.go
import (
	"fmt"
	"sync"
)
type pool struct {
	idle     []iPoolObject
	active   []iPoolObject
	capacity int
	muLock   *sync.Mutex
}
//initPool Initialize the pool
func initPool(poolObjects []iPoolObject) (*pool, error) {
	if len(poolObjects) == 0 {
		return nil, fmt.Errorf("cannot craete a pool of 0 length")
	}
	active := make([]iPoolObject, 0)
	pool := &pool{
		idle:     poolObjects,
		active:   active,
		capacity: len(poolObjects),
		muLock:   new(sync.Mutex),
	}
	return pool, nil
}
func (p *pool) loan() (iPoolObject, error) {
	p.muLock.Lock()
	defer p.muLock.Unlock()
	if len(p.idle) == 0 {
		return nil, fmt.Errorf("no pool object free. Please request after sometime")
	}
	obj := p.idle[0]
	p.idle = p.idle[1:]
	p.active = append(p.active, obj)
	fmt.Printf("Loan Pool Object with ID: %s\n", obj.getID())
	return obj, nil
}
func (p *pool) receive(target iPoolObject) error {
	p.muLock.Lock()
	defer p.muLock.Unlock()
	err := p.remove(target)
	if err != nil {
		return err
	}
	p.idle = append(p.idle, target)
	fmt.Printf("Return Pool Object with ID: %s\n", target.getID())
	return nil
}
func (p *pool) remove(target iPoolObject) error {
	currentActiveLength := len(p.active)
	for i, obj := range p.active {
		if obj.getID() == target.getID() {
			p.active[currentActiveLength-1], p.active[i] = p.active[i], p.active[currentActiveLength-1]
			p.active = p.active[:currentActiveLength-1]
			return nil
		}
	}
	return fmt.Errorf("targe pool object doesn‘t belong to the pool")
}
main.go
import (
	"log"
	"strconv"
)
func main() {
	connections := make([]iPoolObject, 0)
	for i := 0; i < 3; i++ {
		c := &connection{id: strconv.Itoa(i)}
		connections = append(connections, c)
	}
	pool, err := initPool(connections)
	if err != nil {
		log.Fatalf("Init Pool Error: %s", err)
	}
	conn1, err := pool.loan()
	if err != nil {
		log.Fatalf("Pool Loan Error: %s", err)
	}
	conn2, err := pool.loan()
	if err != nil {
		log.Fatalf("Pool Loan Error: %s", err)
	}
	_ = pool.receive(conn1)
	_ = pool.receive(conn2)
}
输出内容为:
Loan Pool Object with ID: 0 Loan Pool Object with ID: 1 Return Pool Object with ID: 0 Return Pool Object with ID: 1
代码已上传至GitHub:zhyea / go-patterns / object-pool-pattern
END!
原文:https://www.cnblogs.com/amunote/p/15259628.html