一、问题
先前在做项目时,遇到了这样一个问题:视图数量多,并且各视图之间的联系紧密(见图1.1)。这样的话,如果继续使用最基本的视图迁移方式来管理视图,就会造成视图之间联系过于紧密,关系过于复杂。最终会导致整个项目模块之间的紧耦合,牵一发而动全身,一旦某个模块更改,可能就会导致其他模块都出问题。另一方面,这也会导致很多相同功能的视图无法复用,同一个项目具有相同功能的视图,你要建几个。很显然,这不科学。
图1.1
所以我想解决视图数量过多,且各视图之间关系紧密复杂的问题。这该怎么办呢?
二、解决思路
我想到了生活中的中介。有人有房子想出租(房东),但是他不想自己去找那些想租房子的人(租客),也不想保存那些想租房子的人的信息。而有些人想租房子(租客),但不知道哪些房源出租,也不想自己存房源的信息。那上面这两类人怎么办呢?他们可以找中介。这就变成了房东-中介-租客之间的关系。这样一来房东就不需要有租客的信息,也能将房子租出去,而租客也不需要房东的信息,也能找到房子,中介成了房东和租客之间的纽带。而中介其实什么都没有,他的职能就是为房东们寻找合适的租客,替租客们匹配合适的房子。这样的好处显而易见,租客和房东之间不会形成复杂的关系网(见图1.2)。
不通过中介
通过中介
图1.2
好的,到目前为止,我们通过中介的存在,切断了房东与租客之间的联系,从而解决了房东和租客们的难题。那实际上上面的做法完全可以用到解决我在先前项目中遇到的问题:视图数量多,并且各视图之间的联系紧密。而这种方法在设计模式中又称为——中介者模式。
中介者模式:用一个对象来封装一系列对象的交互方式。中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互。
想想我们前面提到的房东-中介-租客。房东不需要知道租客的存在,租客同样不需要知道房东的存在,房东和租客只需要通过中介来沟通。租客甚至不用管房东是否改变,房东也不需要知道现在的租客是张三、李四还是王五。很显然,中介者的存在解决了对象与对象(例如房东和租客)之间的紧密而复杂的关系。所有的工作都变的轻松起来。你有房子要出租,你只要告诉中介,去他那登记一下。如果有人想租房子,那他也只要登记一下,告诉中介想要什么样的,中介只需要从房东中间挑选除合适的那个就行。当然了,房东本身也可以是租客(例如你换工作地点了,所以想把现在住的房子租出去,在离公司近的地方再租一个),同样租客也可以是房东。对于中介而言,他们都是客户,只是他们的需求不一样。
三、解决问题
我们也说了那么多了,那在iOS开发中,应该如何应用中介者模式呢?
首先我们需要一个中介,然后我们为中介找一些客户。为了方便,我们就简单为我们的中介找四个客户,两个房东两个租客:
中介:Medium
房东1:LandLord1
房东2:LandLord2
租客1:Tenant1
租客2:Tenant2
这时他们之间的关系见下图(图1.3):
图1.3
但是我们又遇到了问题,如果添加更多的房东和租客呢?难道中介对象都得一个一个将房东和租客对象拥有么?另外,要是有更多的中介呢?显然上面的结构很不合理。既然房东和租客都是中介的客户,那我们不妨抽象出一个客户类型,让所有的房东和租客都属于客户。同样的,无论哪家房产中介结构(链家、21世纪不动产等等),我们统称为中介不久行了吗?那就试试吧。我们抽象出MediumProtocol(中介协议),和CustomerProtocol(客户协议),将中介都遵循中介协议,让房东和租客都遵循客户协议,这样改后的类图如下(图1.4):
图1.4
现在,我们的中介就可以很方便的管理他的客户了,客户之间可以通过中介,根据客户不同的需求寻找合适的对象了。
四、总结
中介者模式很适合用来解耦,例如开篇提出的,视图之间联系紧密关系复杂的问题就很适合用它来解决。它的优势在于,无论你再添加多少视图(客户),对于中介者来说,都一样操作。中介者的存在充分降低了模块间的耦合度,便于扩展。当然了,到底使用什么设计模式,又或者用不用设计模式还得取决于具体项目需求。没有差的技术,只有不恰当的使用方法。还希望大家能够选择合适的架构来做项目。
目前中介者模式用的比较多的,且很典型很流行的是:唱吧、啪啪等应用。至于具体的应用例子我会在后来写出来分享。如果有写的不对的地方,还请告诉我,大家一同探讨探讨。