把一个类的接口变换成客户端所期待的另外一种接口,从而使本来接口不匹配而没法一块儿工做的两个类可以在一块儿工做。适配器模式有类的适配器模式和对象的适配器模式两种形式。前者类之间的耦合度比后者高,且要求程序员了解现有组件库中的相关组件的内部结构,因此应用相对较少些。程序员
优势:app
一、将目标类和适配者类解耦,经过引入一个适配器类来重用现有的适配者类,无需修改原有结构。this
二、增长了类的透明性和复用性,将具体的业务实现过程封装在适配者类中,对于客户端类而言是透明的,并且提升了适配者的复用性,同一适配者类能够在多个不一样的系统中复用。spa
三、灵活性和扩展性都很是好,经过使用配置文件,能够很方便的更换适配器,也能够在不修改原有代码的基础上 增长新的适配器,彻底复合开闭原则。设计
缺点:code
一、一次最多只能适配一个适配者类,不能同时适配多个适配者。对象
二、适配者类不能为最终类,在C#中不能为sealed类blog
三、目标抽象类只能为接口,不能为类,其使用有必定的局限性。继承
适配器模式(Adapter)包含如下主要角色。
目标(Target)接口:当前系统业务所期待的接口,它能够是抽象类或接口。
适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
适配器(Adapter)类:它是一个转换器,经过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。接口
假如用的是苹果手机,可是没有苹果充电线,有华为充电线,那么要使用华为充电线给苹果手机充电,此时就须要一个接口进行转换,适配器模式就是用来完成这种转换的。接下来进行具体实现:
类的适配器模式
namespace 适配器
{
/// 华为充电线 typec 苹果充电线 Lightning
class Client { /// <summary> /// 使用华为充电线给苹果手机充电 /// </summary> /// <param name="args"></param> static void Main(string[] args) { ILightning apple = new Apple(); apple.Recharge(); Console.ReadLine(); } } /// <summary> /// 苹果充电线接口 /// </summary> public interface ILightning { void Recharge(); } /// <summary> /// 华为充电线 /// </summary> public class TypeC { public virtual void HuaweiRecharge() { Console.WriteLine("华为手机充电"); } } /// <summary> /// 实现苹果手机充电 /// </summary> public class Apple : TypeC, ILightning { public void Recharge() { this.HuaweiRecharge(); } } }
以上代码实现图:
对象的适配器模式
namespace 适配器
{
class Client { static void Main(string[] args) { Lightning apple = new Lightning(); apple.Recharge(); Console.ReadKey(); } } public class TypeC { public void HuaweiRecharge() { Console.WriteLine("华为手机充电"); } } public class Lightning : TypeC { public TypeC tc = new TypeC(); public void Recharge() { tc.HuaweiRecharge(); } } }
以上代码实现图:
适配器模式(Adapter)一般适用于如下场景。
一、系统须要复用现有类,而该类的接口不符合系统的需求;
二、想要创建一个可重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在未来引进的类一块儿工做;
三、对于对象适配器模式,在设计里须要改变多个已有子类的接口,若是使用类的适配器模式,就要针对每个子类作一个适配器,而这不太实际。
适配器模式(Adapter)可扩展为双向适配器模式,双向适配器类既能够把适配者接口转换成目标接口,也能够把目标接口转换成适配者接口,其结构图以下。