适配器模式

软件开发中经常遇到的问题:
假设已有一个软件系统,你希望它能和一个新的厂商类库搭配使用,但是这个新厂商所设计出来的接口,不同于旧厂商的接口。如果你不想改变现有的代码,也不能改变厂商的代码,那么你该如何解决这个问题。方法其实很简单,就是写一个类,将新厂商的的接口转成你所期望的接口。如图 
http://images.cnblogs.com/cnblogs_com/wxj1020/adapterModel.JPG

这就是适配器模式。

意图:将一个类的接口转换成客户希望的另外一个接口。Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

结构:对象适配器
http://images.cnblogs.com/cnblogs_com/wxj1020/objectAdapter.JPG 
类适配器
http://images.cnblogs.com/cnblogs_com/wxj1020/classAdapter.JPG 

下面我们来看一个具体的例子来阐释对象适配器:

先准备一只鸭子

1http://www.cnblogs.com/Images/OutliningIndicators/None.gifpublic interface IDuck
2http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif    {
3http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        void Quack(); // 鸭子会呱呱叫
4http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        void Fly();   // 鸭子会飞
5http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif    }

再准备一只绿头鸭

 1http://www.cnblogs.com/Images/OutliningIndicators/None.gifpublic class MallardDuck:IDuck 
 2http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif    {
 3http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        public void Quack()
 4http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif        {
 5http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            Console.WriteLine("Quack");
 6http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif        }
 7http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif
 8http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        public void Fly()
 9http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif        {
10http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            Console.WriteLine("I'm flying");
11http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif        }
12http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif    }

准备一只火鸡

1http://www.cnblogs.com/Images/OutliningIndicators/None.gifpublic interface ITurkey
2http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif    {
3http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        void Gobble();    // 火鸡不会呱呱叫,只会咯咯叫 
4http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        void Fly();       // 火鸡会飞
5http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif    }

准备一只野性十足的火鸡

 1http://www.cnblogs.com/Images/OutliningIndicators/None.gifpublic class WildTurkey :ITurkey
 2http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif    {
 3http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        public void Gobble()
 4http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif        {
 5http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            Console.WriteLine("Gobble,gobble");
 6http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif        }
 7http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        public void Fly()
 8http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif        {
 9http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            Console.WriteLine("I'm flying a short distance");
10http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif        }
11http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif    }

现在,假设你缺鸭子对象,想用一些火鸡对象冒充鸭子,那么你该如何做呢?显然我们的问题是火鸡的接口和鸭子的接口不一样,那么我们可以通过写一个适配器的方法来解决。具体代码如下:

 1http://www.cnblogs.com/Images/OutliningIndicators/None.gif public class TurkeyAdapter:IDuck    // 把火鸡包装成鸭子
 2http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif    {
 3http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        ITurkey turkey;
 4http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif
 5http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        public TurkeyAdapter(ITurkey turkey)
 6http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif        {
 7http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            this.turkey = turkey;    // 火鸡实例化
 8http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif        }
 9http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif
10http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        public void Quack()
11http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif        {
12http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            turkey.Gobble();      // 火鸡冒充鸭子的叫声
13http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif        }
14http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif
15http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif        public void Fly()
16http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif        {
17http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            turkey.Fly();       // 火鸡冒充鸭子飞行
18http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif        }
19http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif    }

现在我们来写一段测试程序:

 1http://www.cnblogs.com/Images/OutliningIndicators/None.gifstatic void Main(string[] args)
 2http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif        {
 3http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            MallardDuck duck = new MallardDuck();
 4http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            WildTurkey turkey = new WildTurkey();
 5http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            IDuck turkeyAdapter = new TurkeyAdapter(turkey);
 6http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif
 7http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            Console.WriteLine("The Turkey says http://www.cnblogs.com/Images/dot.gif");
 8http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            turkey.Gobble();
 9http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            turkey.Fly();
10http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            Console.WriteLine("The Duck says http://www.cnblogs.com/Images/dot.gif");
11http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            testDuck(duck);
12http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            Console.WriteLine("The TurkeyAdapter says http://www.cnblogs.com/Images/dot.gif");
13http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            testDuck(turkeyAdapter);
14http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif
15http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            Console.ReadLine(); 
16http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif        }
17http://www.cnblogs.com/Images/OutliningIndicators/None.gif
18http://www.cnblogs.com/Images/OutliningIndicators/None.gif        static void testDuck(IDuck duck)
19http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif        {
20http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            duck.Quack();
21http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif            duck.Fly();
22http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif        }

效果

image

适配器模式解析:
http://images.cnblogs.com/cnblogs_com/wxj1020/adapterDuck.JPG 

从上面的图中可以看出客户使用适配器的过程:

1)、客户通过目标接口调用适配器的方法对适配器发出请求。

2)、适配器使用被适配者接口把请求转化成被适配者的一个或多个调用接口。

3)、客户接收到调用的结果,但并未察觉这是适配器在起转换作用。

应该注意的地方:

1)、适配器需要做的工作与目标接口的大小成正比,接口越大,需要做的工作越多。

2)、根据实际需要我们可以让适配器实现好几个接口。一句话,要灵活使用模式。

类适配器的代码与对象适配器的代码类似,可以参考结构图仿照着写出来,这里不赘述。

下面说说对象适配器与类适配器的区别

1)、对象适配器使用组合,更富有弹性;类适配器使用继承。

2)、对象适配器可以适配被适配者的子类;类适配器只能覆盖被适配者的行为。

适配器模式的适用性

1)、你想使用一个已经存在的类,而它的接口不符合你的需求。

2)、你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。

3)、你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值