一、什么是中介模式
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other eaxplicitly, and it lets you vary their interaction independently.
用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
中介模式又称调停模式。在很多系统中,多个类很容易相互耦合形成网状结构。中介模式的作用就是讲网状结构分离成星型结构,使得对象间的结构更加简洁,交互更加顺畅。
二、代码框架
class InteractiveObject:
'''进行交互的对象'''
pass
class InteractiveObjectImplA:
'''实现类A'''
pass
class InteractiveObjectImplB:
'''实现类B'''
pass
class Mediator:
'''中介类'''
def __init__(self) -> None:
self._interactiveObjA = InteractiveObjectImplA()
self._interactiveObjB = InteractiveObjectImplB()
def interactive(self):
'''交互操作'''
# 通过self._interactiveObjA和self._interactiveObjB完成相应的交互操作
pass
三、应用
不管是QQ、微信这类支持视频通信的社交软件,还是互联网在线教育产品,都需要和通信设备(扬声器、麦克风、摄像头)进行交互。在PC端,你可能会有多个扬声器、多个摄像头,还可能会在通话过程中进行麦克风切换。如何与这些繁杂的设备进行交互呢?
'''
@author: zyh
@time: 2023/5/5 15:30
@file: mediator.py
'''
from abc import ABCMeta, abstractmethod
from enum import Enum
class DeviceType(Enum):
'''设备类型'''
TypeSpeaker = 1
TypeMicrophone = 2
TypeCamera = 3
class DeviceItem:
'''设备项'''
def __init__(self, id, name, type, isDefault = False):
self._id = id
self._name = name
self._type = type
self._isDefault = isDefault
def __str__(self) -> str:
return 'type: ' + str(self._type) + ', id: ' + str(self._id) + ', name: ' + str(self._name) + ', isDefault: ' + str(self._isDefault)
def getId(self):
return self._id
def getName(self):
return self._name
def getType(self):
return self._type
def isDefault(self):
return self._isDefault
class DeviceList:
'''设备列表'''
def __init__(self):
self._devices = []
def addDevice(self, deviceItem):
self._devices.append(deviceItem)
def getCount(self):
return len(self._devices)
def getByIdx(self, idx):
if idx < 0 or idx >= len(self._devices):
return None
return self._devices[idx]
def getById(self, id):
for item in self._devices:
if item.getId() == id:
return item
return None
class DeviceManager(metaclass=ABCMeta):
@abstractmethod
def emumerate(self):
'''枚举设备列表(在程序初始化时,有设备插拔时都要重新获取设备列表)'''
pass
@abstractmethod
def active(self, deviceId):
'''选择要使用的设备'''
pass
@abstractmethod
def getCurDeviceId(self):
'''获取当前正在使用设备的Id'''
pass
class SpeakerManager(DeviceManager):
'''扬声器设备管理器'''
def __init__(self) -> None:
super().__init__()
self._curDeviceId = None
def emumerate(self):
'''枚举设备列表(真实项目中应该通过驱动程序去读取设备信息,这里仅初始化作为模拟)'''
devices = DeviceList()
devices.addDevice(DeviceItem('369dd760-893b', 'Realtek High Definition Audio', DeviceType.TypeSpeaker))
devices.addDevice(DeviceItem('59357639-6a43', 'NVIDIA High Definition Audio', DeviceType.TypeSpeaker, True))
return devices
def active(self, deviceId):
'''激活指定的设备作为当前要用的设备'''
self._curDeviceId = deviceId
def getCurDeviceId(self):
return self._curDeviceId
class DeviceUtil:
'''设备工具类'''
def __init__(self) -> None:
self._mgrs = {}
self._mgrs[DeviceType.TypeSpeaker] = SpeakerManager()
# 为节省篇幅,MicrophoneManager和CameraManager不再实现
def _getDeviceManager(self, type):
return self._mgrs[type]
def getDeviceList(self, type):
return self._getDeviceManager(type).emumerate()
def active(self, type, deviceId):
self._getDeviceManager(type).active(deviceId)
def getCurDeviceId(self, type):
return self._getDeviceManager(type).getCurDeviceId()
def testDevices():
deviceUtil = DeviceUtil()
deviceList = deviceUtil.getDeviceList(DeviceType.TypeSpeaker)
print('麦克风设备列表:')
if deviceList.getCount() > 0:
# 设置第1个设备为要用的设备
deviceUtil.active(DeviceType.TypeSpeaker, deviceList.getByIdx(0).getId())
for idx in range(deviceList.getCount()):
device = deviceList.getByIdx(idx)
print(device)
print('当前使用的设备为:' + deviceList.getById(deviceUtil.getCurDeviceId(DeviceType.TypeSpeaker)).getName())
if __name__ == '__main__':
testDevices()
输出:
麦克风设备列表:
type: DeviceType.TypeSpeaker, id: 369dd760-893b, name: Realtek High Definition Audio, isDefault: False
type: DeviceType.TypeSpeaker, id: 59357639-6a43, name: NVIDIA High Definition Audio, isDefault: True
当前使用的设备为:Realtek High Definition Audio
四、补充说明
中介者本质上是提供了一个平台,并没有提供实际的行为。
优点:
- 简化了对象之间的交互;
- 将多对多的交互关系转换为一对多的交互关系,更易于理解、维护和拓展;
- 便于复用、降低耦合。
缺点:
- 中介者类承接了所有的交互逻辑,中介者类会变得越来越庞大和复杂,以至于难以维护;
- 中介者出问题会导致多个对象出问题。
应用场景:
- 一组对象以定义良好但复杂的方式进行通信,产生的依赖结构混乱难以理解;
- 一个对象引用其他很多对象并且直接与这些对象通信,导致该对象难以复用;
- 想通过一个中间类来封装多个类中的行为,同时又不想生成太多的子类。