内容摘录自《大话设计模式》
简单地说,就是需要的东西就在面前,但却不能使用,而短时间内又无法改造它,于是我们就想办法适配它。
示例1:电源适配器。有些国家用110V电压,而我们国家用的是220V,但我们的电器,比如笔记本电脑是不能什么电压都能用的,但国家不同,电压可能不相同也是事实,于是就用一个电源适配器,只要是电,不管多少伏,都能把电源变成需要的电压,这就是电源适配器的作用。适配器的意思就是使得一个东西适合另一个东西。
示例2:姚明的翻译。姚明刚到NBA打球,不会英语如何交流?此时翻译就相当于适配器。
在我们不能更改球队的教练、球员和姚明的前提下,我们能做的就是想办法找个适配器。在软件开发中,也就是系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个对象与接口匹配。适配器模式主要用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
Target(这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口)
class Target{
public virtual void Request()
{
Debug.Log("普通请求!");
}
}
Adaptee(需要适配的类)
class Adaptee
{
public void SpecificRequest()
{
Debug.Log("特殊请求!");
}
}
Adapter(通过在内部包装一个adaptee对象,把原接口转换成目标接口)
class Adapter : Target
{
private Adaptee adaptee = new Adaptee(); // 建立一个私有的Adaptee对象
public override void Request()
{
adaptee.SpecificRequest(); // 这样就可以把表面上调用Request()方法变成实际调用SpecificRequest()
}
}
客户端代码
Target target = new Adapter();
target.Request();
在想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就可以考虑用适配器模式。也就是说,两个类所做的事情相同或相似,但是具有不同的接口时要使用它。由于类都共享同一个接口,客户代码可以统一调用同一接口就行了,这样可以更简单、更直接、更紧凑。
通常都是在软件开发后期或维护期再考虑使用它。如果是在世界阶段,类似的功能类的接口应该是相同的。在双方都不太容易修改的时候再使用适配器模式适配。
当然,也有在设计之初就需要考虑用适配器模式的时候。比如公司设计一系统时考虑使用第三方开发组件,而这个组件的接口与我们自己的系统接口是不相同的,而我们也完全没有必要为了迎合它而改动自己的接口,此时就可以考虑用适配器模式来解决接口不同的问题。
后卫、中锋、前锋都是球员,所以应该有一个球员抽象类,有进步和防守的方法。
球员类
// 球员
abstract class Player
{
protected string name;
public Player(string _name)
{
name = _name;
}
public abstract void Attack();
public abstract void Defense();
}
后卫、中锋、前锋类
// 前锋
class Forwards : Player
{
public Forwards(string name):base(name)
{
}
public override void Attack()
{
Debug.Log(string.Format("前锋 {0} 进攻", name));
}
public override void Defense()
{
Debug.Log(string.Format("前锋 {0} 防守", name));
}
}
//中锋
class Center : Player
{
// 与前锋代码类似,略
}
//后卫
class Guards : Player
{
// 与前锋代码类似,略
}
外籍中锋
//外籍中锋
class ForeignCenter
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
public void 进攻()
{
Debug.Log(string.Format("外籍中锋 {0} 进攻", name));
}
public void 防守()
{
Debug.Log(string.Format("外籍中锋 {0} 防守", name));
}
}
翻译者类
// 翻译者
class Translator : Player
{
private ForeignCenter foreignCenter = new ForeignCenter();
public Translator(string name) : base(name)
{
foreignCenter.Name = name;
}
public override void Attack()
{
foreignCenter.进攻();
}
public override void Defense()
{
foreignCenter.防守();
}
}
客户端代码
Player b = new Forwards("巴蒂尔");
b.Attack();
Player ym = new Translator("姚明");
ym.Attack();
ym.Defense();
尽管姚明曾经是不太懂英文,尽管火箭教练和球员也不会学中文,但因为有了翻译者,团队沟通合作成为了可能。