这几个模式比较类似, 都是用作interface, 但有所不同
Proxy, 特点是以假乱真, client在使用的时候就和在使用真正的object一样, 接口完全一致, proxy和object的交互是对client透明的
Adapter, 典型的是电源的adapter, 美标换欧标, 即解决接口不匹配, client和lib都已经写好, 但接口不匹配
Facade, 用于屏蔽子系统的细节, 提供高层接口层
Mediator, 典型的房产中介, 当对象之间关系复杂的时候, 避免对象之间的直接沟通
其中Adapter和Facade是在不得已的情况下采用的, 即已有legacy的系统, 很难改变的情况下的折衷方案
代理模式
代理(Proxy)模式给某一个对象提供一个代理,并由代理对象控制对原对象的引用。
场景, 在软件系统中,有些对象有时候由于跨越网络或者其他的障碍,而不能够或者不想直接访问另一个对象.
这个模式很容易理解, 而且实际应用很多, 如
远程(Remote)代理, 典型的例子, webservice远程调用, RPC
保护(Protect or Access)代理, 控制访问权限
虚拟(Virtual)代理, 当创建消耗资源很大的对象时使用, 如打开很多图片的Html, 会先显示文字, 而图片会下载结束后才显示, 那些未打开的图片框就是用虚拟代理来替代真实图片.
智能引用(Smart Reference)代理:代理需要处理一些额外的事, 如引用计数, 计数为0时释放引用等.
可见这个模式虽然简单, 但是还是很有用的, 代理提供了一层封装, 使客户在访问到真正对象前, 可以做预先的处理, 灵活性很大.
如下图, Subject类定义了RealSubject和Proxy公共的接口, 这样在任何使用RealSubject的地方都可以使用Proxy
class RealSubject : Subject { void Request() { print("Real request");} } class Proxy : Subject { RealSubject realSub; //真实对象 void request() { realSub.Request(); } //可以在访问真实对象时, 添加任何逻辑 }
用户使用直接访问代理
Proxy p = new Proxy()
p.Request()
门面模式
门面模式 (facade)又称外观模式, 为子系统中的一组接口提供一个一致的界面, Facade 模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
这个模式很简单, 当子系统接口比较复杂时, 如果让客户直接使用子系统接口, 有如下问题,
系统难于使用, 客户需要先熟悉复杂的子系统接口
耦合度过高, 当子系统改变时, 会影响到客户类
这样明显违反了迪米特法则和依赖倒转法则, 所以我们的做法就是提供一个相对简单的高层抽象接口来屏蔽底层子系统的细节,从而解决了上面两个问题.
这个模式很简单, 也很常用, 无论你是否知道这个模式
适配器模式
适配器模式 (Adapter), 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
这个模式很简单, 一般用于对已有系统的porting和重用. 这个模式应该是不得已而为之, 因为直接改变原来系统的接口肯定不合适, 所以为了可以重用这个系统必须增加一层adapter.
中介者模式
中介者模式(Mediator), 用一个中介对象来封装一系列的对象交互. 中介者使各对象不需要显式地相互引用, 从而使其耦合松散, 而且可以独立地改变它们之间的交互.
这个模式很好理解, 如房产中介, 留学中介, 当然最大的中介者,联合国. 中介的目的就是解耦合, 使得可以独立地改变和复用各个同事对象和中介者类.
对于面向对象设计, 需要将系统分割成许多对象以增加复用性, 但是对象间激增的相互关联有大大降低了其复用性, 大量的关联导致对象间紧耦合, 修改一个对象就会导致所有和该对象相关联的对象的改动, 牵一发而动全身.
但是面对这种情况, 首先想到的不应该是用中介者模式, 而是系统设计不合理, 设计时应尽量的高聚合低耦合, 而对象间大量的关联导致高耦合, 很有可能是设计不合理, 系统分割过细导致的, 一般通过重新设计就可以解决.
中介者模式适用于, 对象间关系确实很复杂, 如联合国, 各国间关系错综复杂, 于是需要一个中介者把对象间复杂的交换剥离出来交给中介者来处理.
这个模式的缺点就是, 由于把所有对象间交换集中在中介者, 会导致中介者逻辑会过于复杂.
class ConcreteMediator : Mediator { //中介者需要认识所有的同事对象 private ConcreteColleague1 colleague1; private ConcreteColleague2 colleague2; public override void Send(string message,Colleague colleague) { //根据各种条件在不同的同事对象间经行交互 //这段逻辑往往会变的很复杂 if (colleague == colleague1) { colleague2.Notify(message); } else { colleague1.Notify(message); } } } class ConcreteColleague1 : Colleague { protected Mediator mediator; //同事对象只需要认识中介者, 而不需要认识其他任何同事 // Constructor public ConcreteColleague1(Mediator mediator) : base(mediator) { } public void Send(string message) { mediator.Send(message, this); //需要和其他同事交互时, 通过中介者 } public void Notify(string message) //提供给中介者的交互接口 { Console.WriteLine("Colleague1 gets message: "+ message); } } //客户代码 ConcreteMediator m = new ConcreteMediator(); ConcreteColleague1 c1 = new ConcreteColleague1(m); ConcreteColleague2 c2 = new ConcreteColleague2(m); m.Colleague1 = c1; m.Colleague2 = c2; c1.Send("How are you?"); c2.Send("Fine, thanks");