设计模式学习笔记--中介者模式

一.简介


今天来学习一下传说中的中介者模式。说到中介者,我们最容易想到的就是电话中继器,这里我们看看电话的演变过程吧。最早的电话只是两个通话的用户之间相连,这样的结构简单直接,操作最方便。但是随着使用电话的人数多了起来,为每两部电话之间架设一条线路很明显是不可能的,于是就有了电话中继器,记得以前经常看老电影里面,打电话的人要拿起电话,先打给接线员,说“给我接到XXX那”。没错,接线员就相当于中介者。在面向对象设计中,我们经常有很多类对象,对象之间需要交互,而如果对象过多,而每个对象之间都有可能交互的话,最简单的方式就是每个对象保存其他所有可能交互对象的引用,但是这样做有几个问题,第一,需要保存的内容过多,每个对象存一份,很明显是冗余,对象之间的耦合性太高,牵一发而动全身,如果新增一个类,所有之前的类都要修改。为了解决这个问题,中介者模式就应运而生了。
下面看一下中介者模式的定义以及UML类图:
中介者模式(Mediator Pattern):用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式,它是一种对象行为型模式。
设计模式学习笔记--中介者模式_第1张图片
简单解释一下UML类图,我们原本的对象在图中就相当于Colleague同事类,如果没有用中介者模式,他们每个具体的Collegue都需要保存其他所有对象的引用,UML图会灰常凌乱,而通过中介者Mediator,只有中介者自己保存所有对象的引用,而每个具体的同事类只需要和中介者建立关系,就可以和所有的其他同事类对象进行通信,这样大大降低了系统的耦合度。


二.中介者模式的例子


我们就拿电话的例子来看一下,有中介者和没有中介者的情况。


1.没有使用中介者模式的情况


// Design Pattern.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include 
#include 
#include 
using namespace std;

//抽象电话类
class BasePhone
{
public:
	virtual void Call(int num) = 0;
	virtual void Answer() = 0;
};

//移动电话
class MobilePhone : public BasePhone
{
private:
	vector m_phoneVec;
	string m_Name;
public:
	
	MobilePhone(string name)
		: m_Name(name)
	{
	
	}
	//添加通讯录,或者说铺电话线更恰当
	void Add(BasePhone* phone)
	{
		m_phoneVec.push_back(phone);
	}

	//根据号码打电话
	virtual void Call(int num) override
	{
		cout << m_Name << "用手机打电话, ";
		m_phoneVec[num]->Answer();
	}

	//接电话
	virtual void Answer() override
	{
		cout << m_Name << "用手机接电话" << endl;
	}
};

class TelePhone : public BasePhone
{
private:
	vector m_phoneVec;
	string m_Name;
public:
	TelePhone(string name)
		: m_Name(name)
	{

	}

	//添加通讯录,或者说铺电话线更恰当
	void Add(BasePhone* phone)
	{
		m_phoneVec.push_back(phone);
	}

	//根据号码打电话
	virtual void Call(int num) override
	{
		cout << m_Name << "用座机打电话, ";
		m_phoneVec[num]->Answer();
		//这里直接根据基类来处理了,如果有其他处理,耦合性更大
	}

	//接电话
	virtual void Answer() override
	{
		cout << m_Name << "用座机接电话" << endl;
	}
};




int _tmain(int argc, _TCHAR* argv[])
{
	
	MobilePhone* phoneA = new MobilePhone("小明");
	TelePhone*   phoneB = new TelePhone("小刚");
	MobilePhone* phoneC = new MobilePhone("小蔡");

	//为每个对象和每个对象之间都建立联系
	phoneA->Add(phoneA);
	phoneA->Add(phoneB);
	phoneA->Add(phoneC);
	phoneB->Add(phoneA);
	phoneB->Add(phoneB);
	phoneB->Add(phoneC);
	phoneC->Add(phoneA);
	phoneC->Add(phoneB);
	phoneC->Add(phoneC);
	phoneA->Call(1);
	phoneB->Call(2);
	phoneC->Call(0);

	system("pause");
	

	return 0;
}
结果:
小明用手机打电话, 小刚用座机接电话
小刚用座机打电话, 小蔡用手机接电话
小蔡用手机打电话, 小明用手机接电话
请按任意键继续. . .

2.使用了中介者模式的情况


我们发现,每个电话都要与其他两个电话耦合,虽然这里我使用的是基类,可以降低一部分耦合,但是还是感觉代码不够优雅,我们不希望它们彼此之间联系过于密切,于是我们就添加一个中介者。
// Design Pattern.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include 
#include 
#include 
using namespace std;

class BasePhone;
//中介者基类
class BaseMediator
{
public:
	virtual void Call(int num) = 0;
	virtual void Add(BasePhone* phone) = 0;
};


//抽象电话类
class BasePhone
{
protected:
	BaseMediator* m_Mediator;
public:
	//现在我只需要增加一个中介者就可以了
	void SetMediator(BaseMediator* mediator)
	{
		m_Mediator = mediator;
	}

	//通过中介者向其他电话发送信息
	virtual void Call(int num)
	{
		m_Mediator->Call(num);
	}

	virtual void Answer() = 0;
};


//电子电话中继器
class ElectricMediator : public BaseMediator
{
private:
	vector phoneVec;
public:
	//登记电话
	void Add(BasePhone* phone) override
	{
		phoneVec.push_back(phone);
	}

	//拨号
	virtual void Call(int num) override
	{
		phoneVec[num]->Answer();
	}
};

//移动电话
class MobilePhone : public BasePhone
{
private:
	
	string m_Name;
public:
	
	MobilePhone(string name)
		: m_Name(name)
	{
	
	}

	//根据号码打电话
	virtual void Call(int num) override
	{
		cout << m_Name << "用手机打电话, ";
		BasePhone::Call(num);
	}

	//接电话
	virtual void Answer() override
	{
		cout << m_Name << "用手机接电话" << endl;
	}
};

class TelePhone : public BasePhone
{
private:
	string m_Name;
public:
	TelePhone(string name)
		: m_Name(name)
	{

	}

	//根据号码打电话
	virtual void Call(int num) override
	{
		cout << m_Name << "用座机打电话, ";
		BasePhone::Call(num);
	}

	//接电话
	virtual void Answer() override
	{
		cout << m_Name << "用座机接电话" << endl;
	}
};




int _tmain(int argc, _TCHAR* argv[])
{
	
	MobilePhone* phoneA = new MobilePhone("小明");
	TelePhone*   phoneB = new TelePhone("小刚");
	MobilePhone* phoneC = new MobilePhone("小蔡");
	BaseMediator* mediator = new ElectricMediator();

	//向中介者中注册电话
	mediator->Add(phoneA);
	mediator->Add(phoneB);
	mediator->Add(phoneC);

	//电话只保存中介者的引用就可以了
	phoneA->SetMediator(mediator);
	phoneB->SetMediator(mediator);
	phoneC->SetMediator(mediator);

	phoneA->Call(1);
	phoneB->Call(2);
	phoneC->Call(0);

	system("pause");
	

	return 0;
}
结果:
小明用手机打电话, 小刚用座机接电话
小刚用座机打电话, 小蔡用手机接电话
小蔡用手机打电话, 小明用手机接电话
请按任意键继续. . 
.


三.中介者模式的总结


最后,我们来看一下中介者模式的优点,缺点以及使用时机:

优点;
1)去除原来同事对象多对多的交互关系,用中介者和对象的一对多的关系代替,原来的网状结构被星型结构所代替。
2)中介者模式将复杂对象之间的耦合关系解除,新增对象时不需要更改原有代码,符合开放-封闭原则。

缺点:
中介者模式将大量对象的交互细节放在中介者中,中介者职责过重,难以维护。

使用时机:
当我们的系统中对象之间的引用关系呈网状,对象之间都需要相互引用,每个对象都需要引用其他对象时,我们就可以考虑使用中介者模式来重构系统。

你可能感兴趣的:(设计模式,设计模式学习笔记)