适配器模式(16)

今天我们来讲一下适配器模式。下面,我们描述一个场景:

不管是篮球队还是足球队,都会有外援的,在队内训练与安排战术的时候,外援可能听不懂汉语的,那么,他们怎么交流呢,这就需要一个翻译了。其实,这个翻译就起到了一个适配器的效果。

何为适配器模式:将一个接口转换成为客户希望的另外一个接口,使得原本由于接口不兼容而不能在一起的类可以在一起工作。

系统的数据和运行都正确,但是接口不匹配是,我们可以考虑用适配器模式来解决。

好,下面我们来看一下适配器模式的简单的代码结构:

 1     /// <summary>
 2     /// 客户所期待的接口
 3     /// </summary>
 4     class Target
 5     {
 6         public virtual void Request()
 7         {
 8             Console.WriteLine("普通请求!");
 9         }
10     }
11     /// <summary>
12     /// 需要适配的类
13     /// </summary>
14     class Adaptee
15     {
16         public void SpecificRequest()
17         {
18             Console.WriteLine("特殊请求!");
19         }
20     }
21     /// <summary>
22     /// 通过在内部包装一个Adaptee对象,把源接口转换成目标接口
23     /// </summary>
24     class Adapter : Target
25     {
26         private Adaptee adaptee = new Adaptee();//建立一个私有的Adaptee对象
27         public override void Request()
28         {
29             adaptee.SpecificRequest();//这样就可以把表面上调用Request()方法变成实际调用SpecificRequest()
30         }
31     }

客户端调用:

1         public static void Main()
2         {
3             Target target = new Adapter();
4             target.Request();//对于客户端来说,调用的就是Target的Request()
5             Console.ReadKey();
6         }

什么时候使用适配器模式呢?

1、想使用一个已经存在的类,但是它的方法和你要求的方法不同时,应该考虑使用适配器模式。

2、两个类做的事情相似,但是具有不同的接口时,可以考虑使用适配器模式。

使用适配器模式,可以让客户端统一的调用同一个接口就行了。这样可以使代码更直接,更简洁,更紧凑。

好的,下面我们用代码来描述一下NBA的场景

 1     /// <summary>
 2     /// 抽象出来的球员类
 3     /// </summary>
 4     abstract class Player
 5     {
 6         protected string name;
 7 
 8         public Player(string name)
 9         {
10             this.name = name;
11         }
12 
13         public abstract void Attack();//进攻的方法
14         public abstract void Defense();//防守的方法
15     }
16     /// <summary>
17     /// 前锋
18     /// </summary>
19     class Forwards:Player
20     {
21         public Forwards(string name) : base(name)
22         {
23         }
24 
25         public override void Attack()
26         {
27             Console.WriteLine($"前锋{name}进攻");
28         }
29 
30         public override void Defense()
31         {
32             Console.WriteLine($"前锋{name}防守");
33         }
34     }
35     /// <summary>
36     /// 中锋
37     /// </summary>
38     class  Center:Player
39     {
40         public Center(string name) : base(name)
41         {
42         }
43 
44         public override void Attack()
45         {
46             Console.WriteLine($"中锋{name}进攻");
47         }
48 
49         public override void Defense()
50         {
51             Console.WriteLine($"中锋{name}防守");
52         }
53     }
54     /// <summary>
55     /// 后卫
56     /// </summary>
57     class Guards:Player
58     {
59         public Guards(string name) : base(name)
60         {
61         }
62 
63         public override void Attack()
64         {
65             Console.WriteLine($"后卫{name}进攻");
66         }
67 
68         public override void Defense()
69         {
70             Console.WriteLine($"后卫{name}防守");
71         }
72     }

客户端调用:

 1         public static void Main()
 2         {
 3             Player b = new Forwards("巴蒂尔");
 4             b.Attack();
 5             Player m = new Guards("麦克格雷迪");
 6             m.Attack();
 7             Player ym = new Center("姚明");
 8             ym.Attack();//姚明问:Attack()是什么意思?
 9             ym.Defense();//姚明问:Defense()是什么意思?
10             Console.ReadKey();
11         }

这里就有一个问题了,如果姚明刚来NBA是,他对英语不是很精通,所以听不懂英文,所以,他需要一个翻译。换句话说,姚明是外籍中锋,他需要一个翻译者(适配器)来适配他。

我们有一个外籍中锋类

 1     class ForeignCenter
 2     {
 3         private string name;
 4 
 5         public string Name
 6         {
 7             get
 8             {
 9                 return name;
10             }
11 
12             set
13             {
14                 name = value;
15             }
16         }
17 
18         public void 进攻()//表明‘外籍中锋’只懂中文‘进攻’
19         {
20             Console.WriteLine($"外籍中锋{name}进攻");
21         }
22 
23         public void 防守()//表明‘外籍中锋’只懂中文‘防守’
24         {
25             Console.WriteLine($"外籍中锋{name}防守");
26         }
27     }

还有一个翻译者类,将英文翻译成他能听懂的中文"进攻,防守"

 1     class Translator:Player
 2     {
 3         private ForeignCenter wjzf = new ForeignCenter();//声明并实例化一个内部‘外籍中锋’对象,表明翻译者与外籍中锋有关联
 4         public Translator(string name) : base(name)
 5         {
 6             wjzf.Name = name;
 7         }
 8 
 9         public override void Attack()//翻译者将'Attack'翻译为‘进攻’告诉外籍中锋
10         {
11             wjzf.进攻();
12         }
13 
14         public override void Defense()//翻译者将'Attack'翻译为‘防守’告诉外籍中锋
15         {
16             wjzf.防守();
17         }
18     }

客户端:

 1         public static void Main()
 2         {
 3             Player b = new Forwards("巴蒂尔");
 4             b.Attack();
 5             Player m = new Guards("麦克格雷迪");
 6             m.Attack();
 7             Player ym = new Translator("姚明");
 8             ym.Attack();//姚明问:Attack()是什么意思?
 9             ym.Defense();//姚明问:Defense()是什么意思?
10             Console.ReadKey();
11         }

这样,我们就将NBA案例用适配器模式完成了。

其实,在.net中的一些类库,他们也用到了适配器模式,我们经常用到的DataAdapter就是用到了适配器模式的应用。

好了,今天先讲到这里了,下一篇,我们讲 备忘录模式


本系列将持续更新,喜欢的小伙伴可以点一下关注和推荐,谢谢大家的支持

posted @ 2017-02-07 09:32  萌萌丶小魔王  阅读(323)  评论(0编辑  收藏  举报