概念解析
对象池技术,指的是设计一个集合,其中包含了初始化且可以使用的对象,当需要使用相关对象时,直接从中获取,且使用完后需要归还。与前置“享元模式”的区别在于,享元模式没有“占用”的概念,享元对象都是共享的,而对象池中的对象则在“借出”期间是被独占的,可以修改对象的部分属性,而享元独享的属性通常无法被更改。 对象池的两个核心对象:
- 要进行的池化对象:通常是创建和销毁比较耗时,或者本身比较占内存的对象
- 对象池:对象集合,或者管理器,用于管理对象的借用、归还
其优点在于:
- 实现了对象的重复使用,减少内存占用,提升程序性能
缺点在于:
- 借用和归还操作需要成对出现,不然会出现一直占用的情况
- 错误对已归还的对象引用可能引发问题
对象池技术应用非常广泛,Python的“引用计数”思想便是对象池计数的运用,另外如Java的Commons-pool,C++的智能指针等,其他应用如数据库连接池、线程池等。
设计模板
对象池机制的框架模型如下:
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from abc import ABCMeta, abstractmethod
import logging
import time
logging.basicConfig(level=logging.INFO)
class PooledObject():
"""池化对象"""
def __init__(self, obj):
self.__obj = obj
self.__busy = False
def get_object(self):
return self.__obj
def set_object(self, obj):
self.__obj = obj
def is_busy(self):
return self.__busy
def set_busy(self, busy):
self.__busy = busy
class ObjectPool(metaclass=ABCMeta):
"""对象池"""
# 初始化参数
initial_num_of_objects = 0
max_num_of_objects = 50
def __init__(self):
self.__pools = []
for i in range(0, ObjectPool.initial_num_of_objects):
obj = self.create_pooled_object()
self.__pools.append(obj)
@abstractmethod
def create_pooled_object(self):
"""创建池对象,由子类实现该方法"""
pass
def borrow_object(self):
"""借用对象"""
# 如果找到空闲对象,直接返回
obj = self.__find_free_object()
if obj is not None:
logging.info("%x 对象已被借用,time:%s", id(obj),
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())))
return obj
# 对象池未满,则添加新的对象
if len(self.__pools < ObjectPool.max_num_of_objects):
pooled_obj = self.add_object()
if pooled_obj is not None:
pooled_obj.set_busy()
logging.info("%x 对象已被借用,time:%s", id(obj),
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())))
return pooled_obj.get_object()
# 对象池已满且没有空闲对象,返回None
return None
def return_object(self, obj):
"""归还对象"""
for pooled_obj in self.__pools:
if pooled_obj.get_object() == obj:
pooled_obj.set_busy(False)
logging.info("%x 对象已被归还,time:%s", id(obj),
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())))
def add_object(self):
"""添加新对象"""
obj = None
if (len(self.__pools) < ObjectPool.max_num_of_objects):
obj = self.create_pooled_object()
self.__pools.append(obj)
logging.info("添加新对象%x,time:%s", id(obj),
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())))
return obj
def clear(self):
"""清空对象池"""
self.__pools.clear()
def _find_free_object():
"""查找空闲的对象"""
obj = None
for pooled_obj in self.__pools:
if not pooled_obj.is_busy():
obj = pooled_obj.get_object()
pooled_obj.set_busy(True)
break
return obj
实例分析
场景分析:设计共享充电宝的借用机制
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
64
65
66
67
68
69
70
71
72
73
class PowerBank():
"""移动电源"""
def __init__(self, serial_num, electric_quantity):
self.__serial_num = serial_num
self.__electric_quantity = electric_quantity
self.__user = ""
def get_serial_num(self):
return self.__serial_num
def get_electric_quantity(self):
return self.__electric_quantity
def set_user(self, user):
self.__user = user
def get_user(self):
return self.__user
def show_info(self):
print("序列号:%03d 电量:%d%% 使用者:%s" %
(self.__serial_num, self.__electric_quantity, self.__user))
class PowerBankPool(ObjectPool):
"""存放移动电源的智能箱盒"""
__serial_num = 0
@classmethod
def get_serial_num(cls):
cls.__serial_num += 1
return cls.__serial_num
def create_pooled_object(self):
power_bank = PowerBank(PowerBankPool.get_serial_num(), 100)
return PooledObject(power_bank)
def test_object_pool():
power_bank_pool = PowerBankPool()
powerbank1 = power_bank_pool.borrow_object()
if powerbank1 is not None:
powerbank1.set_user("Tony")
powerbank1.show_info()
powerbank2 = power_bank_pool.borrow_object()
if powerbank2 is not None:
powerbank2.set_user("Sam")
powerbank2.show_info()
power_bank_pool.return_object(powerbank1)
powerbank3 = power_bank_pool.borrow_object()
if powerbank3 is not None:
powerbank3.set_user("Aimee")
powerbank3.show_info()
power_bank_pool.return_object(powerbank2)
power_bank_pool.return_object(powerbank3)
power_bank_pool.clear()
"""
测试结果:
INFO:root:1111对象已被借用,time:yyyy-yy-yy yy:yy:yy
序列号:001 电量:100% 使用者:Tony
INFO:root:2222对象已被借用,time:yyyy-yy-yy yy:yy:yy
序列号:002 电量:100% 使用者:Sam
INFO: root:1111对象已归还,time:yyyy-yy-yy yy:yy:yy
INFO:root:3333对象已被借用,time:yyyy-yy-yy yy:yy:yy
序列号:003 电量:100% 使用者:Aimee
INFO: root:2222对象已归还,time:yyyy-yy-yy yy:yy:yy
INFO: root:3333对象已归还,time:yyyy-yy-yy yy:yy:yy
"""