适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
在软件开发中,系统的数据行为都正确,但接口不符,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
下面给出适配器模式的UML图:
下面来看下适配器模式的代码结构图:
namespace ConsoleApplication1 { //Target类,客户所期望的接口 class Target { public virtual void Request() { Console.WriteLine("普通请求!"); } } //Adaptee需要适配的类 class Adaptee { public void SpecificRequest() { Console.WriteLine("特殊的请求!"); } } //Adapter(通过在内部包装一个Adapee对象,把源接口转换成目标接口) class Adapter : Target { private Adaptee adaptee = new Adaptee(); //简历一个私有的Adaptee对象 public override void Request() { adaptee.SpecificRequest(); //这样就可以把表面上调用的Request()方法变成实际调用SpecificRequest() } } class Program { static void Main(string[] args) { Target target = new Target(); //客户端只能够接受Target类 target.Request(); //而且要调用Target类的Request()方法,这样只有通过Adapter白装adaptee了。这就是所为的适配器模式 Console.ReadKey(); } } }
使用一个已经存在的类,但如果它的接口,也就是它的方法和你所要求不相同时,就应该考虑适配器模式。但是适配器模式多少有点亡羊补牢的感觉,因此应该在系统设计之初就规范好接口。
下面回到《大话设计模式》中的要命到NBA打球的例子:
namespace ConsoleApplication1 { abstract class Player { protected string name; public Player(string name) { this.name = name; } public abstract void Attack(); public abstract void Defense(); } //前锋 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); } } //中锋 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); } } //后卫 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); } } //外籍中锋 class ForeignCenter { private string name; public string Name { get { return name; } set { name = value; } } public void 进攻() //注意 外籍中锋的语言不通,因此通过规范的抽象类Player的Attack()方法无法调用 { Console.WriteLine("外籍中锋{0}进攻", name); } public void 防守() { Console.WriteLine("外籍中锋{0}防守", name); } } //翻译者类 class Translator : Player { private ForeignCenter wjzf = new ForeignCenter(); public Translator(string name) : base(name) { wjzf.Name = name; } public override void Attack() //调用翻译者的Attack()就相当于调用了 外籍中锋的进攻,而翻译者类是继承自Player,因此兼容抽象 { wjzf.进攻(); } public override void Defense() { wjzf.防守(); } } class Program { static void Main(string[] args) { Player b = new Forwards("巴蒂尔"); b.Attack(); Player m = new Guards("麦迪"); m.Attack(); Player ym = new Translator("姚明"); //不能直接new外籍中锋对象,因为调用外籍中锋的进攻方法是进攻(),Player类对象无法调用 ym.Attack(); ym.Defense(); Console.ReadKey(); } } }
输出结果如下所示:
适配器模式在.Net中的应用,DataAdapter用作DataSet和数据源之间的适配器以便检索和保存数据。DataAdapter通过映射Fill(这更改了DataSet中的数据以便于数据源中的数据相匹配)和Update(这更改了数据源中的数据以便于DataSet中的数据相匹配)来提供这一适配器。
时间: 2024-10-13 16:09:27