软件设计 2017-02-07
今天我们来讲一下适配器模式。下面,我们描述一个场景:
不管是篮球队还是足球队,都会有外援的,在队内训练与安排战术的时候,外援可能听不懂汉语的,那么,他们怎么交流呢,这就需要一个翻译了。其实,这个翻译就起到了一个适配器的效果。
何为适配器模式:将一个接口转换成为客户希望的另外一个接口,使得原本由于接口不兼容而不能在一起的类可以在一起工作。
系统的数据和运行都正确,但是接口不匹配是,我们可以考虑用适配器模式来解决。
好,下面我们来看一下适配器模式的简单的代码结构:
/// <summary>
/// 客户所期待的接口
/// </summary>
class Target
{
public virtual void Request()
{
Console.WriteLine("普通请求!");
}
}
/// <summary>
/// 需要适配的类
/// </summary>
class Adaptee
{
public void SpecificRequest()
{
Console.WriteLine("特殊请求!");
}
}
/// <summary>
/// 通过在内部包装一个Adaptee对象,把源接口转换成目标接口
/// </summary>
class Adapter : Target
{
private Adaptee adaptee = new Adaptee();//建立一个私有的Adaptee对象
public override void Request()
{
adaptee.SpecificRequest();//这样就可以把表面上调用Request()方法变成实际调用SpecificRequest()
}
} 客户端调用:
public static void Main()
{
Target target = new Adapter();
target.Request();//对于客户端来说,调用的就是Target的Request()
Console.ReadKey();
} 什么时候使用适配器模式呢?
1、想使用一个已经存在的类,但是它的方法和你要求的方法不同时,应该考虑使用适配器模式。
2、两个类做的事情相似,但是具有不同的接口时,可以考虑使用适配器模式。
使用适配器模式,可以让客户端统一的调用同一个接口就行了。这样可以使代码更直接,更简洁,更紧凑。
好的,下面我们用代码来描述一下NBA的场景
/// <summary>
/// 抽象出来的球员类
/// </summary>
abstract class Player
{
protected string name;
public Player(string name)
{
this.name = name;
}
public abstract void Attack();//进攻的方法
public abstract void Defense();//防守的方法
}
/// <summary>
/// 前锋
/// </summary>
class Forwards:Player
{
public Forwards(string name) : base(name)
{
}
public override void Attack()
{
Console.WriteLine($"前锋{name}进攻");
}
public override void Defense()
{
Console.WriteLine($"前锋{name}防守");
}
}
/// <summary>
/// 中锋
/// </summary>
class Center:Player
{
public Center(string name) : base(name)
{
}
public override void Attack()
{
Console.WriteLine($"中锋{name}进攻");
}
public override void Defense()
{
Console.WriteLine($"中锋{name}防守");
}
}
/// <summary>
/// 后卫
/// </summary>
class Guards:Player
{
public Guards(string name) : base(name)
{
}
public override void Attack()
{
Console.WriteLine($"后卫{name}进攻");
}
public override void Defense()
{
Console.WriteLine($"后卫{name}防守");
}
} 客户端调用:
public static void Main()
{
Player b = new Forwards("巴蒂尔");
b.Attack();
Player m = new Guards("麦克格雷迪");
m.Attack();
Player ym = new Center("姚明");
ym.Attack();//姚明问:Attack()是什么意思?
ym.Defense();//姚明问:Defense()是什么意思?
Console.ReadKey();
} 这里就有一个问题了,如果姚明刚来NBA是,他对英语不是很精通,所以听不懂英文,所以,他需要一个翻译。换句话说,姚明是外籍中锋,他需要一个翻译者(适配器)来适配他。
我们有一个外籍中锋类
class ForeignCenter
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public void 进攻()//表明‘外籍中锋’只懂中文‘进攻’
{
Console.WriteLine($"外籍中锋{name}进攻");
}
public void 防守()//表明‘外籍中锋’只懂中文‘防守’
{
Console.WriteLine($"外籍中锋{name}防守");
}
} 还有一个翻译者类,将英文翻译成他能听懂的中文"进攻,防守"
class Translator:Player
{
private ForeignCenter wjzf = new ForeignCenter();//声明并实例化一个内部‘外籍中锋’对象,表明翻译者与外籍中锋有关联
public Translator(string name) : base(name)
{
wjzf.Name = name;
}
public override void Attack()//翻译者将'Attack'翻译为‘进攻’告诉外籍中锋
{
wjzf.进攻();
}
public override void Defense()//翻译者将'Attack'翻译为‘防守’告诉外籍中锋
{
wjzf.防守();
}
} 客户端:
public static void Main()
{
Player b = new Forwards("巴蒂尔");
b.Attack();
Player m = new Guards("麦克格雷迪");
m.Attack();
Player ym = new Translator("姚明");
ym.Attack();//姚明问:Attack()是什么意思?
ym.Defense();//姚明问:Defense()是什么意思?
Console.ReadKey();
} 这样,我们就将NBA案例用适配器模式完成了。
其实,在.net中的一些类库,他们也用到了适配器模式,我们经常用到的DataAdapter就是用到了适配器模式的应用。
好了,今天先讲到这里了,下一篇,我们讲 备忘录模式
本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持
前几篇介绍了设计模式的特性并且详细讲解了4种创建型模式,创建型模式是负责如何产生对象实例的,接下来讲讲结构型模式。结构型模式是解析类和对象的内部结构和外部组合,通过优化程序结构解决模块之间的耦合问题。