面向对象编程思想

时间:2023-01-02 09:59:54

一、引言

前两天休息日在网上打QQ斗地主,每盘结束后腾讯游戏平台会自动计算输赢的欢乐豆,嗯?挺好的,平时在面对面玩斗地主时,一盘游戏结束后,我们需要了解每个人的出牌状况,然后算出来输赢。现在有了游戏平台,玩家之间计算输赢这个操作交给了游戏平台,我们不再需要了解每个人的出牌状况。在软件设计中,我们将解决这种业务场景的模式称之为中介者模式

二、中介者模式

定义:用一个中介对象来封装一系列对象的交互。中介者使各对象不需要显式的相互引用,从而使其耦合松散,而且独立改变它们之间的交互。

下面是中介者模式结构图:

面向对象编程思想

为什么要使用中介者模式?

如果不使用中介者模式,各个同事对象将相互引用,如果每个对象都与多个对象交互时,将形成下图所示网状结构:

面向对象编程思想

分析:上图中每个对象之间过度耦合,不利于类的复用也不利于扩展。假如对象一变化了将可能引起与它直接相依赖的所有对象的调整,所以同事对象之间直接依赖不是好的设计。

如果采用中介者模式,那么对象之间的关系将变成下图所示星型结构;

面向对象编程思想

分析:使用中介者模式后,任何一个同事对象的变化,只会影响中介者和类本身,不会像之前设计中一个对象变化,将会引用所有与之关联的对象变化

场景:两个人本金都是100,在一起打牌,每盘结束后计算两个人的金额

下面是不使用中介者模式的demo:

面向对象编程思想面向对象编程思想
     //抽象同事类  充当牌友类
public abstract class Colleague
{
public int Number
{
get;
set;
}
public abstract void Win(int number, Colleague colleague);
}
//牌友A类
public class ConcreteColleagueA : Colleague
{
public override void Win(int number, Colleague colleague)
{
this.Number += number;
colleague.Number
-= number;
}
}
//牌友B类
class ConcreteColleagueB : Colleague
{
public override void Win(int number, Colleague colleague)
{
this.Number += number;
colleague.Number
-= number;
}
}
class Program
{
static void Main(string[] args)
{
//A和B两个人打牌
Colleague colleagueA = new ConcreteColleagueA();
Colleague colleagueB
= new ConcreteColleagueB();
colleagueA.Number
= 100;
colleagueB.Number
= 100;
//A赢了B就输钱
colleagueA.Win(5, colleagueB);
Console.WriteLine($
"A的数量为{colleagueA.Number}");
Console.WriteLine($
"B的数量为{colleagueA.Number}");

Console.Read();
}
}
View Code

面向对象编程思想

分析:上述确实解决了场景中的问题,牌友A和牌友B都依赖于抽象,从而降低同事类之间的耦合度。这样的设计中,牌友A的变化会引起牌友B的变化,但是如果现在要新增一个牌友C、D、E呢?设计到多个对象的变化时,当前同事类需要了解其他所有涉及的同事类状况,这时就需要修改同事类了,而且,多个牌友计算输赢时任何一个人计算错误,都会导致整个业务场景中的计算错误。基于此思考,能不能把计算的钱的任务交给程序做呢?譬如QQ斗地主。。。即引入中介者对象来协调各个对象之间的关系

下面是引入中介者对象的代码demo

面向对象编程思想面向对象编程思想
//抽象同事类
public abstract class Colleague
{
public int Number
{
get;
set;
}
public abstract void Win(int number, Mediator mediator);
}
//抽象中介者类
public abstract class Mediator
{
public ConcreteColleagueA A;
public ConcreteColleagueB B;
public Mediator(ConcreteColleagueA a, ConcreteColleagueB b)
{
A
= a;
B
= b;
}
public abstract void AWin(int number);
public abstract void BWin(int number);
}
public class ConcreteColleagueA : Colleague
{
public override void Win(int number, Mediator mediator)
{
mediator.AWin(number);
}
}
public class ConcreteColleagueB : Colleague
{
public override void Win(int number, Mediator mediator)
{
mediator.BWin(number);
}
}
class ConcreteMediator : Mediator
{
public ConcreteMediator(ConcreteColleagueA a, ConcreteColleagueB b) : base(a,b)
{ }

public override void AWin(int number)
{
A.Number
+= number;
B.Number
-= number;
}
public override void BWin(int number)
{
A.Number
-= number;
B.Number
+= number;
}
}
class Program
{
static void Main(string[] args)
{
ConcreteColleagueA concreteColleagueA
= new ConcreteColleagueA();
ConcreteColleagueB concreteColleagueB
= new ConcreteColleagueB();
ConcreteMediator concreteMediator
= new ConcreteMediator(concreteColleagueA, concreteColleagueB);
concreteColleagueA.Number
= 100;
concreteColleagueB.Number
= 100;
concreteMediator.AWin(
5);
Console.WriteLine($
"A的数量为{concreteColleagueA.Number}");
Console.WriteLine($
"B的数量为{concreteColleagueB.Number}");
Console.WriteLine();
Console.Read();
}
}
View Code

分析:运行结果和上面不使用中介者模式的代码运行结果一致,这样如果某个牌友类变化时,只会影响到该变化的牌友类和中介者类,从而解决上面代码中的问题。

但是此时如果要新增一个牌友类,我们就不得不修改抽象中介者类,还可以再完善一下吗?完全可以,我们可以结合观察者模式,在抽象中介者类中保存一个抽象牌友类的集合,添加保存删除牌友的方法管理集合,然后在具体的中介者类中,修改AWin()、BWin()循环遍历执行改变自己和其他牌友的钱数。此时仍然存在一个问题,新增牌友时,我们虽然不需要修改抽象中介者类,但是还是要在具体中介者类中添加CWin()方法,这时可以此采用状态模式来解决问题,具体会在下一个专题中介绍。

下面是大话设计模式中的例子辅助理解中介者模式:

面向对象编程思想面向对象编程思想
    abstract class Colleague
{
protected Mediator mediator;
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
}
abstract class Mediator
{
public abstract void Send(string message, Colleague colleague);
}
class ConcreteColleagueA : Colleague
{
public ConcreteColleagueA(Mediator mediator) : base(mediator)
{

}
public void Send(string message)
{
mediator.Send(message,
this);
}
public void Notify(string message)
{
Console.WriteLine(
"同事A得到消息:"+message);
}
}
class ConcreteColleagueB : Colleague
{
public ConcreteColleagueB(Mediator mediator) : base(mediator)
{

}
public void Send(string message)
{
mediator.Send(message,
this);
}
public void Notify(string message)
{
Console.WriteLine(
"同事B得到消息:" + message);
}
}
class ConcreteMediator : Mediator
{
private ConcreteColleagueA concreteColleagueA;
private ConcreteColleagueB concreteColleagueB;
public ConcreteColleagueA ConcreteColleagueA
{
set { concreteColleagueA = value; }
}
public ConcreteColleagueB ConcreteColleagueB
{
set { concreteColleagueB = value; }
}
public override void Send(string message, Colleague colleague)
{
if(colleague==concreteColleagueA)
{
concreteColleagueB.Notify(message);
}
else if(colleague==concreteColleagueB)
{
concreteColleagueA.Notify(message);
}
}
}
class Program
{
static void Main(string[] args)
{
ConcreteMediator concreteMediator
= new ConcreteMediator();
ConcreteColleagueA concreteColleagueA
= new ConcreteColleagueA(concreteMediator);
ConcreteColleagueB concreteColleagueB
= new ConcreteColleagueB(concreteMediator);
concreteMediator.ConcreteColleagueA
= concreteColleagueA;
concreteMediator.ConcreteColleagueB
= concreteColleagueB;
concreteColleagueA.Send(
"你吃过饭了吗?");
concreteColleagueB.Send(
"我吃过了");
Console.Read();
}
}
View Code

面向对象编程思想

优点:

1.将系统各个对象之间的关系进行封装,将各个同事类解耦,使系统松耦合

2.将对象间一对多关系转变为一对一关联,使对象间关系易于理解和维护

3.提高系统灵活性,使各个同事类独立而易于复用

缺点:

1.中介者承担的责任太重,一旦中介者出现问题,整个系统将会受到影响

2.新增加一个同事类时,不得不修改抽象中介者类和具体的中介者类

适用场景:

1.一组定义好的关系,要进行复杂的通信(如最开始对象间关系成网状结构)时,使用中介者模式可以使同事类间关系更清晰

2.想通过一个中间类来封装多个类中的行为

 

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

参照:

1.大话设计模式

2.http://www.cnblogs.com/zhili/p/MediatorPattern.html