前言:设计模式
以前讲过装饰者模式,将对象包装起来并赋予新的职责,这一章咱们也会将对象进行包装,只不过是让它们看起来不像本身而像是别的东西。这样就能够在设计中将类的接口转化为想要的接口,以实现同的接口,此外还将讲述另外一个模式,将对象包装起来以简化接口。测试
真实世界的适配器好比位于美式插头和欧式插座之间的交流电适配器。面向对象的适配器是什么呢?this
面向对象的适配器是将一个接口转化成另外一个接口,以符合客户的指望。设计
例如已有的一个软件系统,但愿它能和一个新的厂商类库搭配使用,可是这个厂商设计出来的接口不一样于旧的接口,而你又不想改变现有的代码,因此这个时候就须要一个适配器来完成现有系统和新的厂商类库的对接。code
咱们在策略模式里举例讲的鸭子。看一个简化版的示例。对象
publicinterface Duck { void Quack();//鸭子叫 void Fly();//鸭子飞 }
publicclass MallardDuck:Duck { public void Quack() { Console.WriteLine(" Quack"); } public void Fly() { Console.WriteLine(" Fly"); } }
publicinterface Turkey { void Gobble();//咯咯叫 void Fly();//飞 } publicclass WildTurkey : Turkey { public void Gobble() { Console.WriteLine(" GobbleGobble"); } public void Fly() { Console.WriteLine(" I'm flyinga short distance "); } }
publicclass TurkeyAdapter:Duck//实现想转换成的类型接口 { Turkey turkey; public TurkeyAdapter(Turkey turkey)//取得适配器的对象引用,并利用构造获得这个引用 { this.turkey = turkey; } public void Quack()//实现接口中的全部方法 { turkey.Gobble(); } public void Fly() { for(var i=0;i<5;i++) turkey.Fly(); } }
MallardDuckduck = new MallardDuck(); WildTurkey turkey = newWildTurkey(); Duck turkeyAdapter = newTurkeyAdapter(turkey); Console.WriteLine(" The turkeysyas ..."); turkey.Gobble(); turkey.Fly(); Console.WriteLine(" The Ducksays ..."); turkeyAdapter.Quack(); turkeyAdapter.Fly(); Console.Read();
结果以下:继承
客户使用适配器的过程以下:接口
l 客户经过目标接口调用适配器的方法对适配器发出请求。ci
l 适配器使用被适配者接口把请求转化成被适配者的一个或多个调用接口。get
l 客户接收到调用的结果。
适配器模式:将一个类的接口,转化成客户指望的另外一个接口。适配器可让本来接口不兼容的类能够合做无间。
该模式能够经过建立适配器进行接口转换,让不兼容的接口变得兼容,让客户从实现的接口解耦。其类图以下:
该适配器充满了OO设计的原则:使用对象组合,以修改的接口包装被适配者。被是陪者的任何子类均可以搭配着适配器使用。该模式是把客户和接口绑定起来的,而非和实现绑定。
实际上有两种适配器:对象适配器和类适配器。类适配器经过多重继承来实现,而对象适配器利用组合的方式将请求传递给被适配者。
类适配器图:
外观模式:提供了一个统一的接口,用来访问子系统的一群接口。外观定义了一个高层接口,让子系统更容易使用。
外观模式容许咱们让客户和子系统之间避免紧耦合。类图以下:
最少知识原则:只和你的密友谈话。
最少知识原则告诉咱们要减小对象之间的交互。该原则但愿在设计时,不要让太多的类耦合在一块儿,省得修改系统中的一部分,会影响到其余部分。
怎样避免让太多的类耦合在一块儿呢?主要有如下的方针:
就对象而言,在该对象的方法内,咱们只应该调用属于如下范围的方法:
l 该对象自己
l 被当作方法的参数而传递进来的对象
l 此方法所建立或实例化的任何对象
l 对象的任何组件
以下示例:
(不要采用这个原则)从气象站取得了温度计对象,而后再从温度计对象取得问题
Publicfloat GetTemp() { Thermometerthermometer=station.GetThermometer(); return thermometer.GetTemperature(); }
(采用这个原则)咱们在气象站中加进一个方法,用来向温度计请求温度。能够减小咱们所依赖的类的数据。
Publicfloat GetTemp() { Return station.GetTemperature(); }
l 当须要使用一个现有的类而其接口并不符合你的须要时,就须要使用适配器。
l 当须要简化并统一一个很大的接口或者一群负责的接口时,使用外观。
l 适配器改变接口以符合客户的指望。
l 外观将客户从一个复杂的子系统中解耦。
l 实现一个适配器的难易视目标接口的大小与复杂而定。
l 实现一个外观,须要将子系统组合进外观中,而后将工做委托给子系统执行。
l 适配器分为对象适配器和类适配器,类适配器须要多重继承。
l 能够为一个子系统实现一个以上的外观。
l 适配器将一个对象包装起来以改变其接口;装饰者将一个对象包装起来以增长新的行为和责任;而外观将一群对象“包装”起来以简化其接口。