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

适用场景:

  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\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!

GoLang设计模式06 - 对象池模式的更多相关文章

  1. 游戏开发设计模式之对象池模式(unity3d 示例实现)

    前篇:游戏开发设计模式之命令模式(unity3d 示例实现) 博主才学尚浅,难免会有错误,尤其是设计模式这种极富禅意且需要大量经验的东西,如果哪里书写错误或有遗漏,还请各位前辈指正. 原理:从一个固定 ...

  2. java设计模式之实现对象池模式示例分享

    http://www.jb51.net/article/46941.htm 对象池模式经常用在频繁创建.销毁对象,且对象创建.销毁开销很大的场景,比如数据库连接池.线程池.任务队列池等.本代码简单,没 ...

  3. 对象池模式(Object Pool Pattern)

    本文节选自<设计模式就该这样学> 1 对象池模式的定义 对象池模式(Object Pool Pattern),是创建型设计模式的一种,将对象预先创建并初始化后放入对象池中,对象提供者就能利 ...

  4. C++设计模式 之 “对象性能” 模式:Singleton、Flyweight

    “对象性能”模式 面向对象很好地解决了“抽象”的问题,但是必不可免地要付出一定的代价.对于通常情况来讲,面向对象的成本大都可以忽略不计.但是某些情况,面向对象所带来的成本必须谨慎处理. 典型模式 # ...

  5. C++设计模式 之 “对象创建”模式:Factory Method、Abstract Factory、Prototype、Builder

    part 0 “对象创建”模式 通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 典型模式 Fact ...

  6. GoLang设计模式3 - 抽象工厂模式

    之前我们介绍了工厂设计模式,现在我们再看一下抽象工厂设计模式.抽象工程模式顾名思义就是对工厂模式的一层抽象,也是创建型模式的一种,通常用来创建一组存在相关性的对象. UML类图大致如下: 类图比较复杂 ...

  7. GoLang设计模式07 - 责任链模式

    责任链模式是一种行为型设计模式.在这种模式中,会为请求创建一条由多个Handler组成的链路.每一个进入的请求,都会经过这条链路.这条链路上的Handler可以选择如下操作: 处理请求或跳过处理 决定 ...

  8. php设计模式 数据对象映射模式

    数据对象映射模式,是将对象和数据存储映射起来,对一个对象的操作会映射为对数据存储的操作. 在代码中实现数据对象映射模式,实现一个ORM类,将复杂的sql语句映射成对象属性的操作.对象关系映射(Obje ...

  9. 游戏设计模式——Unity对象池

    对象池这个名字听起来很玄乎,其实就是将一系列需要反复创建和销毁的对象存储在一个看不到的地方,下次用同样的东西时往这里取,类似于一个存放备用物质的仓库. 它的好处就是避免了反复实例化个体的运算,能减少大 ...

随机推荐

  1. FreeRTOS-04-内核控制函数+时间管理函数

    说明 本文仅作为学习FreeRTOS的记录文档,作为初学者肯定很多理解不对甚至错误的地方,望网友指正. FreeRTOS是一个RTOS(实时操作系统)系统,支持抢占式.合作式和时间片调度.适用于微处理 ...

  2. Vulnhub -- DC3靶机渗透

    @ 目录 信息收集 尝试攻击 获取shell方法1 获取shell方法2 获取shell方法3 拿到root权限 拿FLAG 总结 信息收集 kali的ip为192.168.200.4,扫描出一个IP ...

  3. Cloud-init的安装和使用 --以ubuntu-server-14.04-amd64为例

    by hyc 1.Cloud-init安装 已有了一个安装好系统的镜像. 镜像名:ubuntu-test-14.04-server-amd64.img 用户名:user 密码:1 主机名:ubuntu ...

  4. 实战爬取某网站图片-Python

    直接上代码 1 #!/usr/bin/python 2 # -*- coding: UTF-8 -*- 3 from bs4 import BeautifulSoup 4 import request ...

  5. [数据结构]ODT(珂朵莉树)实现及其应用,带图

    [数据结构]ODT(珂朵莉树)实现及其应用,带图 本文只发布于博客园,其他地方若出现本文均是盗版 算法引入 需要一种这样的数据结构,需要支持区间的修改,区间不同值的分别操作. 一般的,我们会想到用线段 ...

  6. GraphQL API vs REST API

    REST是构建API的一种流行方法,而且比GraphQL应用更广泛,让我们看看GraphQL和REST的区别. Rest是一个概念 REST是一个事实上的架构标准,但它实际上没有规范,有大量的非官方定 ...

  7. Emlog V6.0.0代码审计笔记

    前言 emlog是一套基于PHP和MySQL的博客及CMS建站系统. emlog v6.0.0存在后台SQL注入漏洞. 分析 官网下载emlog最新版v6.0.0,本地搭建. 前台功能不多,参数基本都 ...

  8. git flow版本

    feature 分支:开发者进行功能开发的分支. develop 分支:对开发的功能进行集成的分支. release 分支:负责版本发布的分支. hotfix 分支:对线上缺陷进行修复工作的分支,热修 ...

  9. nginx使用geo模块进行接口访问限制

    背景需求: 对api接口 /api/inner 进行ip访问限制 # ip白名单geo $ip_list { default 0; 111.111.111.111 1; } server { list ...

  10. Mac 证书错误

    在 Mac 操作系统安装 Python 3.6 或以上版本时,可能会遇到证书错误:Error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify ...