[设计模式]行为型-中介者模式

前言

中介者模式(Mediator Pattern)通过在中间引入一个层,实现对象的解耦,以便对象之间的交互通过该层发生。

主要角色:

  • 中介者(Mediator):一个接口,主要用于提供注册同事对象与转发同事对象信息的抽象方法。
  • 同事(Colleague):一个接口,主要用于存储中介者对象,提供与具体同事对象进行交互的抽象方法,实现所有相互影响的具体同事类的公共功能。
  • 具体同事(Concrete Colleague):实现同事接口的类,只知道自己的行为,不了解其他具体同事类的情况,但它们都认识中介者对象。
  • 具体中介者(Concret Mediator):实现中介者接口的类,主要用于封装多种组件间的关系。具体中介者通常会存储所有组件的引用并对其进行管理,有时甚至会对其生命周期进行管理。

优点

  • Mediator 将原本分布于多个对象间的行为集中在一起,作为一个独立的概念并将其封装在一个对象中,简化了对象之间的交互。
  • 将多个调用者与多个实现者之间多对多的交互关系,转换为一对多的交互关系,一对多的交互关系更易于理解、维护和扩展,大大减少了多个对象之间相互交叉引用的情况。

缺点

  • 中介者承接了所有的交互逻辑,交互的复杂度转变成了中介者的复杂度,中介者类会变得越来越庞大和复杂,以至于难以维护。
  • 中介者出问题会导致多个使用者同时出问题。

应用场景

  • 一组对象以定义良好但复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。
  • 一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。
  • 想通过一个中间类来封装多个类中的行为,同时又不想生成太多的子类。

示例代码

Go

package mediator

import (
	"log/slog"
)

// 同事接口, 火车
type Train interface {
	Arrive()
	Depart()
	PermitArrive()
}

// 中介者接口
type Mediator interface {
	CanArrive(Train) bool
	NotifyAboutDeparture()
}

// 具体同事类, 客运火车
type PassengerTrain struct {
	Mediator Mediator
}

func (p *PassengerTrain) Arrive() {
	if !p.Mediator.CanArrive(p) {
		slog.Info("PassengerTrain: Arrival blocked, waiting")
		return
	}
	slog.Info("PassengerTrain: Arrived")
}

func (p *PassengerTrain) Depart() {
	slog.Info("PassengerTrain: Leaving")
	p.Mediator.NotifyAboutDeparture()
}

func (p *PassengerTrain) PermitArrive() {
	slog.Info("PassengerTrain: Arrival permitted")
	p.Arrive()
}

// 具体同事类, 货运火车
type FreightTrain struct {
	Mediator Mediator
}

func (f *FreightTrain) Arrive() {
	if !f.Mediator.CanArrive(f) {
		slog.Info("FreightTrain: Arrival blocked, waiting")
		return
	}
	slog.Info("FreightTrain: Arrived")
}

func (f *FreightTrain) Depart() {
	slog.Info("FreightTrain: Leaving")
	f.Mediator.NotifyAboutDeparture()
}

func (f *FreightTrain) PermitArrive() {
	slog.Info("FreightTrain: Arrival permitted")
	f.Arrive()
}

// 具体中介者类
type StationManager struct {
	isPlatformFree bool
	trainQueue     []Train
}

func NewStationManager() *StationManager {
	return &StationManager{
		isPlatformFree: true,
	}
}

func (s *StationManager) CanArrive(t Train) bool {
	if s.isPlatformFree {
		s.isPlatformFree = false
		return true
	}
	s.trainQueue = append(s.trainQueue, t)
	return false
}

func (s *StationManager) NotifyAboutDeparture() {
	if !s.isPlatformFree {
		s.isPlatformFree = true
	}

	if len(s.trainQueue) > 0 {
		firstTrainInQueue := s.trainQueue[0]
		s.trainQueue = s.trainQueue[1:]
		firstTrainInQueue.PermitArrive()
	}
}

测试代码

package mediator

import (
	"testing"
)

func TestMediator(t *testing.T) {
	stationManager := NewStationManager()

	passengerTrain := &PassengerTrain{
		Mediator: stationManager,
	}

	freightTrain := &FreightTrain{
		Mediator: stationManager,
	}

	passengerTrain.Arrive()
	freightTrain.Arrive()
	passengerTrain.Depart()
}

测试运行输出

2025/03/19 22:24:26 INFO PassengerTrain: Arrived
2025/03/19 22:24:26 INFO FreightTrain: Arrival blocked, waiting
2025/03/19 22:24:26 INFO PassengerTrain: Leaving
2025/03/19 22:24:26 INFO FreightTrain: Arrival permitted
2025/03/19 22:24:26 INFO FreightTrain: Arrived

Python

from typing import List

class HouseInfo:
    """房源信息"""
    def __init__(self, area, price, hasWindow, hasBathroom, hasKitchen, address, owner):
        self.__area = area
        self.__price = price
        self.__hasWindow = hasWindow
        self.__hasBathroom = hasBathroom
        self.__hasKitchen = hasKitchen
        self.__address = address
        self.__owner = owner

    def get_address(self):
        return self.__address
    
    def get_owner_name(self):
        return self.__owner.get_name()
    
    def show_info(self, is_show_owner = True):
        print(f"面积: {self.__area} 平方米")
        print(f"价格: {self.__price} 元")
        print(f"是否有窗: {'有' if self.__hasWindow else '无'}")
        print(f"是否有卫生间: {'有' if self.__hasBathroom else '无'}")
        print(f"是否有厨房: {'有' if self.__hasKitchen else '无'}")
        print(f"地址: {self.__address}")
        print(f"房东: {self.get_owner_name() if is_show_owner else ''}")

class HouseAgency:
    """房屋中介"""
    def __init__(self, name: str):
        self.__house_infos: List[HouseInfo] = []
        self.__name = name

    def get_name(self):
        return self.__name
    
    def add_house_info(self, house_info: HouseInfo):
        self.__house_infos.append(house_info)

    def remove_house_info(self, house_info: HouseInfo):
        for info in self.__house_infos:
            if info == house_info:
                self.__house_infos.remove(info)

    def get_search_condition(self, description):
        """将用户描述信息转换为搜索条件"""
        return description
    
    def get_match_infos(self, search_condition):
        """根据搜索条件获取匹配房源信息"""
        print(f"{self.get_name()} 找到以下适合的房源: ")
        for info in self.__house_infos:
            info.show_info(False)
        return self.__house_infos
    
    def sign_contract(self, house_info: HouseInfo, period):
        """与房东签订协议"""
        print(f"{self.get_name()}和房东{house_info.get_owner_name()}签署{house_info.get_address()}的房子的租赁合同, 租期{period}年。合同期内, {self.get_name()}有权对其进行使用和转租")

    def sign_contracts(self, period):
        for info in self.__house_infos:
            self.sign_contract(info, period)

class Landlord:
    """房东"""
    def __init__(self, name: str):
        self.__name = name
        self.__house_info: HouseInfo = None

    def get_name(self):
        return self.__name
    
    def set_house_info(self, address, area, price, hasWindow, hasBathroom, hasKitchen):
        self.__house_info = HouseInfo(address=address, area=area, price=price, hasWindow=hasWindow, hasBathroom=hasBathroom, hasKitchen=hasKitchen, owner=self)

    def publish_house_info(self, agency: HouseAgency):
        agency.add_house_info(self.__house_info)
        print(f"{self.get_name()} 在 {agency.get_name()} 发布房源出租信息:")
        self.__house_info.show_info()

class Tenant:
    """租户"""
    def __init__(self, name: str):
        self.__name = name

    def get_name(self):
        return self.__name
    
    def find_house(self, description, agency: HouseAgency):
        print(f"我是 {self.get_name()}, 想租一个{description}的房子")
        return agency.get_match_infos(agency.get_search_condition(description))
    
    def see_house(self, house_infos: List[HouseInfo]):
        """看房, 选择最合意的房子"""
        size = len(house_infos)
        return house_infos[size-1]
    
    def sign_contract(self, house_info: HouseInfo, agency: HouseAgency, period):
        """与中介签订协议"""
        print(f"{self.get_name()}与中介{agency.get_name()}签订{house_info.get_address()}的房屋租赁合同, 租期{period}年。合同期内, {self.get_name()}有权对其进行使用")

if __name__ == "__main__":
    beijia = HouseAgency("贝家")

    zhangsan = Landlord("张三")
    zhangsan.set_house_info("大东门", 50, 2500, True, True, True)
    zhangsan.publish_house_info(beijia)

    zhangsi = Landlord("张四")
    zhangsi.set_house_info("西七里塘", 40, 1800, True, True, False)
    zhangsi.publish_house_info(beijia)

    zhangwu = Landlord("张五")
    zhangwu.set_house_info("青年公寓", 10, 600, True, False, False)
    zhangwu.publish_house_info(beijia)

    beijia.sign_contracts(3)

    lihua = Tenant("李华")
    house_infos = lihua.find_house("面积大于40, 价格小于2000, 有窗, 有卫生间, 无厨房", beijia)
    print("看房中...")

    appropriate_house = lihua.see_house(house_infos)
    lihua.sign_contract(appropriate_house, beijia, 1)
posted @ 2025-03-19 22:29  花酒锄作田  阅读(40)  评论(0)    收藏  举报