介绍:
适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口。Ada[ter模式,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
解决问题:即Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
模式结构图
在想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式。
两个类所做的事情相同或相似,但是具有不同的接口时要使用它。而且由于类都共享一个接口
客户代码可以统一调用同一接口就行了,这样应该可以更简单、更直接、更紧凑
适配器模式的基本代码
客户端代码
static void Main(string[] args)
{
Target target = new Adapter(); //对客户端来说,调用的就是Target的Request()
target.Request();
Console.Read();
}
Target(这是客户所期望的接口。目标可以是具体的或抽象的类,也可以是接口)
class Target
{
public virtual void Request()
{
Console.WriteLine("普通请求!");
}
}
Adaptee(需要适配的类)
class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("特殊需求!");
}
}
Adpter(通过在内部包装一个Adaptee对象,把接口装换成目标接口)
class Adapter : Target
{
private Adaptee adaptee = new Adaptee(); //建立一个私有的Adaptee对象
public override void Request()
{
adaptee.SpecificRequest(); //这样就可以把表面上调用Request()方法变成实际调用SpecialRequest()
}
}
例子:
姚明去了NBA但是,当时的姚明的英语水平并不是很好,所以在与教练和队友之间需要有一个翻译来帮助他理解。
代码结构图
球员类
abstract class Player
{
protected string name;
public Player(string name)
{
this.name = name;
}
public abstract void Attack(); //进攻的方法
public abstract void Defence(); //防守的方法
}
前锋
class Forwards : Player
{
public Forwards(string name)
: base(name)
{
}
public override void Attack()
{
Console.WriteLine("前锋{0} 进攻",name);
}
public override void Defence()
{
Console.WriteLine("前锋{0} 防守", name);
}
}
中锋
class Center : Player
{
public Center(string name)
: base(name)
{
}
public override void Attack()
{
Console.WriteLine("中锋{0} 进攻", name);
}
public override void Defence()
{
Console.WriteLine("中锋{0} 防守", name);
}
}
后卫
class Guards : Player
{
public Guards(string name)
: base(name)
{
}
public override void Attack()
{
Console.WriteLine("后卫{0} 进攻", name);
}
public override void Defence()
{
Console.WriteLine("后卫{0} 防守", name);
}
}
客户端代码
static void Main(string[] args)
{
Player b = new Forwards("巴蒂尔");
b.Attack();
Player m = new Guards("麦克格雷迪");
m.Attack();
Player ym = new Center("姚明");
ym.Attack(); //姚明问;“Attack”和“Defence”是什么意思
ym.Defence();
Console.Read();
}
运行效果
模式总结
优点:
1 通过适配器,客户端可以调用同一接口,因而对客户端来说是透明的。这样做更简单、更直接、更紧凑。
2 复用了现存的类,解决了现存类和复用环境要求不一致的问题。
3 将目标类和适配者类解耦,通过引入一个适配器类重用现有的适配者类,而无需修改原有代码。
4 一个对象适配器可以把多个不同的适配者类适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点:
对于对象适配器来说,更换适配器的实现过程比较复杂。
适用环境
1.系统需要使用一些现有的类,而这些类的接口不符合系统的需要,甚至美誉这些类的源代码
2.创建一个可以重复使用的类,用于和一些彼此之间没有太大关联的类,包括一些可能在将来引进的类一起工作
适配器模式不可不用,也不可过度使用。如果能事先预防接口不同的问题,不匹配问题就不会发生;在有小的接口不统一的问题发生时,及时重构,问题不至于扩大;只有碰到无法改变原有设计和代码的情况时,才考虑适配。事后控制不如事中控制,事中控制不如事前控制。