概念:
享元模式(Flyweight Pattern)是一种结构型设计模式,用于减少创建对象的数量,以提高应用程序的性能。享元模式通过共享尽可能多的数据来减少内存使用。
功能: 享元模式的主要功能是节省内存。
优点:
缺点:
应用场景:
使用方式:
在应用程序开发中的应用:
享元模式的工作原理是通过共享尽可能多的数据来减少内存使用。
在享元模式中,创建对象的过程被分为两个阶段。
- 第一阶段,创建对象并初始化所有属性。
- 第二阶段,所有属性被设置为共享属性,以便在创建其他对象时可以共享这些属性。
通过这种方式,一个对象可以通过多次使用相同的属性来减少内存使用。
我们以一个图书馆管理系统为例,假设在该系统中有成千上万本书籍,而这些书籍中大部分属性都是相同的,例如书名、作者、出版社等信息,只有少部分属性是不同的,例如ISBN编码、出版日期等信息。如果我们为每本书都创建一个独立的对象,将会占用大量的内存,因此应该考虑使用享元模式来管理这些对象。
首先,我们需要定义一个 Book 接口,以便创建书籍对象,并在接口中定义书籍属性的方法:
接着,我们定义一个具体的书籍类 BookImpl,用于实现 Book 接口:
接下来,我们定义一个书籍工厂类 BookFactory,用于创建和管理书籍对象:
最后,我们在客户端代码中,使用 BookFactory 来创建和获取书籍对象:
from abc import ABC,abstractmethod
# ***************************************************************************使用亨元模式 创建大量相似对象的应用程序,减少内存使用
class Book(ABC):
'''
书籍接口,定义书籍属性 书名、作者、出版社
'''
@abstractmethod
def get_book_name(self):
pass
@abstractmethod
def get_book_author(self):
pass
@abstractmethod
def get_book_publisher(self):
pass
class BookImpl(Book):
'''
定义具体书籍类,实现Book方法
'''
def __init__(self, name, author, publisher):
self.name = name
self.author = author
self.publisher = publisher
def get_book_name(self):
return self.name
def get_book_author(self):
return self.author
def get_book_publisher(self):
return self.publisher
class BookFactory():
'''
定义书籍工厂类,用于创建和管理书籍对象
'''
def __init__(self):
self.books = {}
def get_book(self, name, author, publisher):
'''
创建书籍对象,已存在相同属性的书籍对象,直接返回已有对象
'''
if (name, author, publisher) not in self.books:
# 判断不存在相同的属性,将新的书籍添加到池子中
self.books[(name, author, publisher)] = BookImpl(name, author, publisher)
return self.books[(name, author, publisher)]
# 创建书籍工厂对象
fac = BookFactory()
# 获取书籍
book1 = fac.get_book("book1", "author1", "pub1")
book2 = fac.get_book("book2", "author2", "pub2")
book3 = fac.get_book("book3", "author3", "pub3")
# 打印书籍信息
print(book1.get_book_name(), book1.get_book_author(), book1.get_book_publisher())
print(book2.get_book_name())
print(book3.get_book_name())
运行结果:
book1 author1 pub1
book2
book3
在上面的代码中,我们创建了三本书籍对象,并打印了它们的属性。在创建书籍对象时,我们使用了 BookFactory 来管理书籍对象的池子,以便重用已经存在的对象。通过共享相同属性的对象,我们可以减少内存的使用,提高程序的性能。
在实际应用中,享元模式通常用于管理大量的共享对象,例如线程池、连接池等。下面我们以连接池为例,来说明如何使用 Python 实现连接池的功能。
连接池是一种常见的数据库连接管理方式。在传统的数据库连接方式中,每次需要连接数据库时,都会重新创建一个数据库连接对象。这样会消耗大量的系统资源,并且每次创建连接对象都需要进行一系列的初始化工作,导致连接对象的创建速度比较缓慢。而使用连接池,则可以通过共享连接对象来提高程序的性能。
首先,我们需要定义一个数据库连接池 ConnectionPool 类,其中包含两个方法:init() 方法用于初始化连接池对象,create_connection() 方法用于创建数据库连接对象。
其中,max_connections 参数表示连接池中最大的连接数,如果连接池中已经存在 max_connections 个连接对象,则直接返回第一个连接对象。如果连接池中的连接对象不足 max_connections 个,则创建一个新的连接对象,并添加到连接池中。
接下来,我们在客户端代码中,通过 ConnectionPool 来获取连接对象:
import paramiko
class SSHConnectionPool():
'''
SSH 连接池
'''
def __init__(self, host, port, username, password, max_connection = 10):
# 初始化连接池对象
self.host = host
self.port = port
self.username = username
self.password = password
self.max_connection = max_connection
self.connections = []
def create_connection(self):
# 创建ssh对象
if len(self.connections) < self.max_connection:
conn = paramiko.SSHClient()
conn.set_missing_host_key_policy(paramiko.AutoAddPolicy)
conn.connect(self.host, self.port, self.username, self.password)
self.connections.append(conn)
else:
conn = self.connections.pop(0)
return conn
# 创建连接池对象
pool = SSHConnectionPool(host="192.168.1.***", port=22, username="root", password="123456")
# 获取SSH连接对象
conn1 = pool.create_connection()
conn2 = pool.create_connection()
conn3 = pool.create_connection()
# 执行命令
stdin, stdout, stderr = conn1.exec_command("ls")
print(stdout.readlines())
# 关闭连接
conn1.close()
conn2.close()
conn3.close()
运行结果:
['anaconda-ks.cfg\n', 'Desktop\n', 'Documents\n', 'Downloads\n', 'ifconfig_20230607.txt\n', 'initial-setup-ks.cfg\n', 'kmod-r8125-9.003.05-1.el7_8.elrepo.x86_64.rpm\n', 'Music\n', 'Pictures\n', 'Public\n', 'Templates\n', 'test\n', 'Videos\n']
在上面的代码中,我们创建了一个连接池对象 pool,并获取了三个连接对象 conn1、conn2、conn3。通过连接对象获取游标对象,并执行 SQL 语句。最后,我们将连接对象关闭,并释放资源。
使用连接池可以有效地减少数据库连接的创建和销毁过程,减少系统资源的占用,提高程序的性能。