zoukankan      html  css  js  c++  java
  • GoLang设计模式06

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

    适用场景:

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

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

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

    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
    ", 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
    ", 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!


    仅是学习笔记,难免出错,望不吝指点
  • 相关阅读:
    flutter canvas 简单绘画直线
    Yapi 部署及遇到的坑
    flutter 时间选择器第三方插件返回时间格式说明
    windows + flutter + vscode 连接其他模拟器
    flutter 配置环境
    flutter 返回键监听
    flutter 自定义主题切换
    flutter Provide 状态管理篇
    flutter 本地存储 (shared_preferences)
    JS做倒计时的例题
  • 原文地址:https://www.cnblogs.com/amunote/p/15259628.html
Copyright © 2011-2022 走看看