一、描述
對象類與對象類之間的交互通信統一由另外一箇中介類來控制 ,對象通過中介類對其他對象交互,中介類起着控制器的作用。
二、優劣勢
優點:降低類與類之間的耦合性,對象與對象之間不再相互引用,把類與類之間的交互抽離出來方便擴展。
缺點:關係過於複雜的話,如對象與對象類交互功能比較多時,中介類將異常龐大,不利於後期維護。
三、需求
實現房東與租客2個人之間的交流,主要有說話和聆聽。
四、不使用設計模式
都不考慮設計了,直接擼代碼。
3個類,
Person.cs -人基類
Landlord.cs -房東類
Tenant.cs -租客類
// 人基類
public class Person
{
public string name;
public Person(string str)
{
name = str;
}
public virtual void Talk(Person person, string str)
{
}
public virtual void Listen(Person person, string str)
{
}
}
//房東類
public class Landlord : Person
{
public Landlord(string str) : base(str)
{
}
public override void Talk(Person person, string str)
{
Debug.Log("房東-" + name + "發出消息:" + str);
person.Listen(this, str);
}
public override void Listen(Person person, string str)
{
Debug.Log("房東-" + name + "收到來自"+person.name+"的消息:" + str);
}
}
//租客類
public class Tenant : Person
{
public Tenant(string str) : base(str)
{
}
public override void Talk(Person person, string str)
{
Debug.Log("租客-" + name + "發出消息:" + str);
person.Listen(this, str);
}
public override void Listen(Person person, string str)
{
Debug.Log("租客-" + name + "收到來自" + person.name + "的消息:" + str);
}
}
//客戶端調用
public static void main(string[] args)
{
Landlord landlord = new Landlord("李姐");
Tenant tenant = new Tenant("小趙");
tenant.Talk(landlord, "房東啊,月租多少?");
landlord.Talk(tenant, "就一千三,很便宜的!");
}
運行結果
小結:每次房東或者租客要說話時,都得把接收者對象傳遞過去,在說話方法時調用接收對象的listen方法,此處爲耦合部分。
五、使用設計模式
通過添加一箇中介,房東與租客的通話都交給他來處理,這樣房東與租客就不需要互相認識再去溝通了。
5個類,
Person.cs -人基類
Landlord.cs -房東類
Tenant.cs -租客類
Mediator -中介者基類
PlayerMediator -中介類實現
// 人基類
public class Person
{
public string name;
protected Mediator mediator;
public Person(string str)
{
name = str;
}
public void SetMediator(Mediator m)
{
mediator = m;
}
public virtual void Talk(string str)
{
}
public virtual void Listen(Person person, string str)
{
}
}
//房東類
public class Landlord : Person
{
public Landlord(string str) : base(str)
{
}
public override void Talk(string str)
{
Debug.Log("房東-" + name + "發出消息:" + str);
mediator.Listen(this,str);
}
public override void Listen(Person person, string str)
{
Debug.Log("房東-" + name + "收到來自" + person.name + "的消息:" + str);
}
}
//租客類
public class Tenant : Person
{
public Tenant(string str) : base(str)
{
}
public override void Talk(string str)
{
Debug.Log("租客-" + name + "發出消息:" + str);
mediator.Listen(this, str);
}
public override void Listen(Person person, string str)
{
Debug.Log("租客-" + name + "收到來自" + person.name + "的消息:" + str);
}
}
//中介基類
public abstract class Mediator
{
public abstract void Listen(Person person, string str);
}
//中介者具體實現
public class PlayerMediator : Mediator
{
private Tenant tenant;//租客
private Landlord landlord;//房東
public void SetTenant(Tenant t)
{
tenant = t;
}
public void SetLandlord(Landlord l)
{
landlord = l;
}
//根據傳過來的對象來決定接收者
public override void Listen(Person person, string str)
{
if (person== tenant)
{
landlord.Listen(person,str);
}
else if (person == landlord)
{
tenant.Listen(person, str);
}
}
}
//客戶端調用
public static void main(string[] args)
{
Landlord landlord = new Landlord("李姐");
Tenant tenant = new Tenant("小趙");
PlayerMediator playerMediator = new PlayerMediator();
playerMediator.SetLandlord(landlord);
playerMediator.SetTenant(tenant);
landlord.SetMediator(playerMediator);
tenant.SetMediator(playerMediator);
tenant.Talk("房東啊,月租多少?");
landlord.Talk("就一千三,很便宜的!");
}
運行結果
小結:房東與租客在說話時不需要在他talk裏去處理調用接收者的listent方法了,而是由其持有的中介對象PlayerMediator去處理這些事,解耦步驟就在這點上,剝離了與接收者的listent通信,雖然客戶端調用的步驟多了一些賦值步驟,但是面向對象就是這樣, 不要介意這個,還是很穩的放心。
六、設計圖
通過學習,我們瞭解到了中介者模式的應用,我們把剛剛的實現方式畫出來。
七、進階例子
(1)需求:班長通知消息給每一個同學。
(2)分析:按照笨方法,班長得走到每一個人面前跟他說一遍,有幾個人就得說幾次,也就是班長類得調用無數次talk方法然後依次傳入每一個同學類對象,當不只是班長髮言,假如2個同學要說悄悄話了,那麼就變成了這樣:,如下圖。
爲了解決這個問題,我們引入了交流工具QQ,變成如下:
這樣是不是清晰多了,這裏的QQ就是我們的中介對象。
(3)實現代碼:
5個類,
Student.cs -學生基類
BanZhang.cs -班長類
TongXue.cs -學生類
Mediator -中介者基類
QQMediator -中介QQ類實現
// 學生基類
public class Student
{
public string name;
//中介者qq對象
protected Mediator mediator;
public Student(string str)
{
name = str;
}
public void SetMediator(Mediator m)
{
mediator = m;
}
//在羣裏說話
public virtual void TalkAll(string str)
{
mediator.TalkAll(this, str);
}
//跟一個人私聊,參數爲私聊對象
public virtual void TalkOne(Student student, string str)
{
mediator.TalkOne(this, student, str);
}
public virtual void Listen(Student student, string str)
{
Debug.Log(name + "接收到了來自" + student.name + "的消息:" + str);
}
}
//班長類
public class BanZhang : Student
{
public BanZhang(string str) : base(str)
{
}
}
//同學類
public class TongXue : Student
{
public TongXue(string str) : base(str)
{
}
}
//中介基類
public abstract class Mediator
{
//私聊
public abstract void TalkOne(Student talkMan, Student listentMan, string str);
//羣聊
public abstract void TalkAll(Student talkMan, string str);
}
//中介者QQ具體實現
public class QQMediator : Mediator
{
//保存有參與進來qq的人員
private List<Student> studentList;
public QQMediator()
{
studentList = new List<Student>();
}
//添加人員到qq
public void AddStudent(params Student[] s)
{
studentList.AddRange(s);
}
//羣聊
public override void TalkAll(Student talkMan, string str)
{
if (studentList.Contains(talkMan))
{
foreach (Student item in studentList)
{
if (item != talkMan)
{
item.Listen(talkMan, str);
}
}
}
}
//私聊
public override void TalkOne(Student talkMan, Student listentMan, string str)
{
if (studentList.Contains(talkMan) && studentList.Contains(listentMan))
{
listentMan.Listen(talkMan,str);
}
}
}
//客戶端調用
public static void main(string[] args)
{
QQMediator qqediator = new QQMediator();
BanZhang banZhang = new BanZhang("班長");
banZhang.SetMediator(qqediator);
TongXue tongXue1 = new TongXue("張無忌");
tongXue1.SetMediator(qqediator);
TongXue tongXue2 = new TongXue("趙敏");
tongXue2.SetMediator(qqediator);
qqediator.AddStudent(banZhang, tongXue1, tongXue2);
//班長廣播通知消息
banZhang.TalkAll("下午第三節課上體育!");
//也可以這麼調用: qqediator.TalkAll(banZhang, "下午第三節課上體育!");
Debug.Log("----------------------分割線----------------------");
//私聊
tongXue1.TalkOne(tongXue2, "小敏,體育課跟我玩吧");
tongXue2.TalkOne(tongXue1, "好的哦");
//也可以這麼調用: tongXue2.TalkOne(tongXue1,tongXue2, "下午第三節課上體育!");
}
運行結果:
八、總結
覺得有用就留下評論吧^-^