GoLang设计模式06 - 对象池模式


这次介绍最后一个创建型模式——对象池模式。顾名思义,对象池模式就是预先初始化创建好多个对象,并将之保存在一个池子里。当需要的时候,客户端就可以从池子里申请一个对象使用,使用完以后再将之放回到池子里。池子里的对象在应用运行期间永远不会被破坏或回收。

适用场景:

  1. 当需要的对象的创建成本比较高,且该类型的对象在应用运行期间只需要有限的数量
  2. 对象是不可变的
  3. 性能原因:预创建的对象可以显著提升应用性能

我们在开发中最熟悉的对象池应该是数据库连接池了。因为网络因素,数据库连接池中的每个对象的创建成本都比较高,且应用在运行期间会需要多个数据库连接对象。另外,每个数据库的连接池中对象的属性都是一样的,且在运行期间这些对象的属性几乎通常都是不可变的。

来看个模拟的数据库连接对象池模型的例子。

iPoolObject.go

1 2 3 4 type iPoolObject interface {     //This is any id which can be used to compare two different pool objects     getID() string }

connection.go

1 2 3 4 5 6 7 type connection struct {     id string }   func (c *connection) getID() string {     return c.id }

pool.go

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 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

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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) }

输出内容为:

1 2 3 4 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