模式动机

在软件开发中采用类似于电源适配器的设计和编码技巧被称为适配器模式。
通常情况下,客户端可以通过目标类的接口访问它所提供的服务。有时,现有的类可以满足客户类的功能需要,但是它所提供的接口不一定是客户类所期望的,这可能是因为现有类中方法名与目标类中定义的方法名不一致等原因所导致的。
在这种情况下,现有的接口需要转化为客户类期望的接口,这样保证了对现有类的重用。如果不进行这样的转化,客户类就不能利用现有类所提供的功能,适配器模式可以完成这样的转化。
在适配器模式中可以定义一个包装类,包装不兼容接口的对象,这个包装类指的就是适配器(Adapter),它所包装的对象就是适配者(Adaptee),即被适配的类。
适配器提供客户类需要的接口,适配器的实现就是把客户类的请求转化为对适配者的相应接口的调用。也就是说:当客户类调用适配器的方法时,在适配器类的内部将调用适配者类的方法,而这个过程对客户类是透明的,客户类并不直接访问适配者类。因此,适配器可以使由于接口不兼容而不能交互的类可以一起工作。这就是适配器模式的模式动机。

模式定义
适配器模式(Adapter Pattern) :将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。
Adapter Pattern: Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
Frequency of use: medium high
UML图

模式结构
适配器模式包含如下角色:
Target:目标抽象类
Adapter:适配器类
Adaptee:适配者类
Client:客户类

模式实例与解析
在NBA我需要翻译—适配器模式
体系结构

Target:目标抽象类 Player.cs

namespace AdapterPattern
{
// 球员
abstract class Player
{
protected string name;
public Player(string name)
{
this.name = name;
} public abstract void Attack();//进攻方法
public abstract void Defense(); //防守方法
}
}

Adaptee:适配者类 ForeignCenter.cs 需要适配的类

using System;

namespace AdapterPattern
{
// 外籍中锋
class ForeignCenter
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
} public void 进攻()
{
Console.WriteLine("外籍中锋 {0} 进攻", name);
} public void 防守()
{
Console.WriteLine("外籍中锋 {0} 防守", name);
}
}
}

Adapter:适配器类 Translator.cs
通过在内部包装一个Adaptee对象,把源接口转换成目标接口

namespace AdapterPattern
{
// 翻译者
class Translator : Player
{
private ForeignCenter wzjf = new ForeignCenter(); public Translator(string name)
: base(name)
{
wzjf.Name = name;
} public override void Attack()
{
wzjf.进攻();
} public override void Defense()
{
wzjf.防守();
}
}
}

Forwards.cs

using System;

namespace AdapterPattern
{
//前锋
class Forwards : Player
{
public Forwards(string name)
: base(name)
{ }
public override void Attack()
{
Console.WriteLine("前锋 {0} 进攻", name);
}
public override void Defense()
{
Console.WriteLine("前锋 {0} 防守", name);
} }
}

Center.cs

using System;

namespace AdapterPattern
{
class Center : Player
{
public Center(string name)
: base(name)
{ }
public override void Attack()
{
Console.WriteLine("中锋 {0} 进攻", name);
}
public override void Defense()
{
Console.WriteLine("中锋 {0} 防守", name);
}
}
}

Guards.cs

using System;

namespace AdapterPattern
{
class Guards : Player
{
public Guards(string name)
: base(name)
{ }
public override void Attack()
{
Console.WriteLine("后卫 {0} 进攻", name);
}
public override void Defense()
{
Console.WriteLine("后卫 {0} 防守", name);
}
}
}

Client:客户类

using System;

namespace AdapterPattern
{
class Program
{
static void Main(string[] args)
{
Player b = new Forwards("巴蒂尔");
b.Attack(); Player m = new Guards("麦克格雷迪");
m.Attack(); Player ym = new Translator("姚明");
ym.Attack();
ym.Defense(); Console.Read();
}
}
}

模式优缺点
 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。

类适配器模式还具有如下优点:
由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
类适配器模式的缺点如下:
对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。

对象适配器模式还具有如下优点:
一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
对象适配器模式的缺点如下:
与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。

模式适用环境
在以下情况下可以使用适配器模式:
系统需要使用现有的类,而这些类的接口不符合系统的需要。
想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。

模式应用
Sun公司在1996年公开了Java语言的数据库连接工具JDBC,JDBC使得Java语言程序能够与数据库连接,并使用SQL语言来查询和操作数据。JDBC给出一个客户端通用的抽象接口,每一个具体数据库引擎(如SQL Server、Oracle、MySQL等)的JDBC驱动软件都是一个介于JDBC接口和数据库引擎接口之间的适配器软件。抽象的JDBC接口和各个数据库引擎API之间都需要相应的适配器软件,这就是为各个不同数据库引擎准备的驱动程序。

深入浅出设计模式——适配器模式(Adapter Pattern)的更多相关文章

  1. 设计模式 - 适配器模式(adapter pattern) 具体解释

    适配器模式(adapter pattern) 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 适配器模式(adapter pattern): 将一个类的接 ...

  2. 设计模式 - 适配器模式(adapter pattern) 枚举器和迭代器 具体解释

    适配器模式(adapter pattern) 枚举器和迭代器 具体解释 本文地址: http://blog.csdn.net/caroline_wendy 參考适配器模式(adapter patter ...

  3. C#设计模式——适配器模式(Adapter Pattern)

    一.概述在软件开发中,常常会想要复用一个已经存在的组件,但该组件的接口却与我们的需要不相符,这时我们可以创建一个适配器,在需复用的组件的接口和我们需要的接口间进行转换,从而能够正常的使用需复用的组件. ...

  4. 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern)

    原文:乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) 作者:webabc ...

  5. 怎样让孩子爱上设计模式 —— 7.适配器模式(Adapter Pattern)

    怎样让孩子爱上设计模式 -- 7.适配器模式(Adapter Pattern) 标签: 设计模式初涉 概念相关 定义: 适配器模式把一个类的接口变换成client所期待的还有一种接口,从而 使原本因接 ...

  6. 设计模式系列之适配器模式(Adapter Pattern)——不兼容结构的协调

    模式概述 模式定义 模式结构图 模式伪代码 类适配器,双向适配器,缺省适配器 类适配器 双向适配器 缺省适配器 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 主要优点 主要缺点 适 ...

  7. 二十四种设计模式:适配器模式(Adapter Pattern)

    适配器模式(Adapter Pattern) 介绍将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.示例有一个Message实体类 ...

  8. 【设计模式】适配器模式 Adapter Pattern

    适配器模式在软件开发界使用及其广泛,在工业界,现实中也是屡见不鲜.比如手机充电器,笔记本充电器,广播接收器,电视接收器等等.都是适配器. 适配器主要作用是让本来不兼容的两个事物兼容和谐的一起工作.比如 ...

  9. 设计模式(七): 通过转接头来观察"适配器模式"(Adapter Pattern)

    在前面一篇博客中介绍了“命令模式”(Command Pattern),今天博客的主题是“适配器模式”(Adapter Pattern).适配器模式用处还是比较多的,如果你对“适配器模式”理解呢,那么自 ...

随机推荐

  1. JS写的CRC16校验算法(查表法)

    var CRC = {}; CRC._auchCRCHi = [ 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0 ...

  2. GDC2016 【全境封锁】的全局照明技术

    现在全力支持公司的GAD平台了,很多的内部分享也可以放出来 http://gad.qq.com/article/detail/7159232

  3. java 截取pdf

    最近在读一本电子书,pdf中频繁引用后文的内容(页码),必须实时的跳过去看,但是扫描版的pdf的页码往往从封面就开始计数,而且盗版还经常有一些做广告的页面,这就导致pdf reader 索引的页面并不 ...

  4. 白话学习MVC(七)Action的执行一

    一.概述 在此系列开篇的时候介绍了MVC的生命周期 , 对于请求的处理,都是将相应的类的方法注册到HttpApplication事件中,通过事件的依次执行从而完成对请求的处理.对于MVC来说,请求是先 ...

  5. C#中Brush、Color、String相互转换WPF/Silverlight

    //部分方法只适用于WPF,在SL中不能用 using System.Windows.Media; 1.String转换成Color Color color = (Color)ColorConvert ...

  6. xavante运行cgilua流程

    安装软件 需要安装三个lua 库:  xavante wsapi cgilua luarocks install xavante http://keplerproject.github.io/xava ...

  7. 在LaTeX文档中插入图片的几种常用的方法

    LaTeX中一般只直接支持插入eps(Encapsulated PostScript)格式的图形文件, 因此在图片插入latex文档之前应先设法得到图片的eps格式的文件. 在LaTeX文档中插入图片 ...

  8. Java使用占位符拼接字符串

    大家知道,在C#编程中,可以用占位符来拼接字符串,用起来非常的方便. 特别是需要进行大量的参数拼接的时候,比如: Console.WriteLine(String.Format("该域名{0 ...

  9. PHP二维数组提取函数----把不需要的数据剔除

    首先说明一些这个函数的应用场景,比如说你得到的数据是个二维数组,里面的很多成员其实是不必要的,比如说api调用后不必要给别人返回一些用不到的垃圾数据吧,如下是代码. <?php /* * del ...

  10. python对json的操作总结

    Json简介:Json,全名 JavaScript Object Notation,是一种轻量级的数据交换格式.Json最广泛的应用是作为AJAX中web服务器和客户端的通讯的数据格式.现在也常用于h ...