入门设计模式之中介者模式(十八)

一、描述

        对象类与对象类之间的交互通信统一由另外一个中介类来控制 ,对象通过中介类对其他对象交互,中介类起着控制器的作用。

二、优劣势


优点:降低类与类之间的耦合性,对象与对象之间不再相互引用,把类与类之间的交互抽离出来方便扩展。
缺点:关系过于复杂的话,如对象与对象类交互功能比较多时,中介类将异常庞大,不利于后期维护。

三、需求

      实现房东与租客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, "下午第三节课上体育!");
}

运行结果:

八、总结

 觉得有用就留下评论吧^-^

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章