第九课 适配器模式

第九课 适配器模式

       今天我们来看一看适配器模式。这是一个常用的模式,作用也很简单,举例说明一下。现在我们有一个团队,在做一个大型项目。A同志负责写一些基类。它定义了一个读写操作类,由一个方法readbyte(),正如名字说说的,将文本读取,返回byte[]的方法。现在呢,B定义了一个接口,里面包含了2个方法,readByte(),readString()。并且设计者基于这个接口做了很多应用。现在C同志犯愁了。A只给了他一个readByte(),而根据设计,他需要用B的接口。可是现在没有一个readString()的方法呀。那么怎么办呢。他就需要实现一个适配器。将A的类适配到B的接口上去。简单的说就是利用一下Areadbyte()方法,来实现一下readString()方法,这样不就满足了B的接口了吗,也能满足设计者的需求。这就是适配器模式了。就像美国的电源是110v,中国是220v。美国电器来到中国用,必须要通过一个 变压器(适配器) 来把电流改成110v才能正常使用。中间的适配器,就想C写的实现一样。

       转一段原话:在 GoF 的经典著作《设计模式》中指出: Adapter 模式的目的就是将类的接口转换成客户对象需要的接口, Adapter 模式使原本不相容的接口变的相容。也就是说我们有一个可以满足我们需要的对象,但是她的接口却不是象我们所期望的那样,而我们现在所需要的就是创建一个新的接口,让原本的接口能够满足我们的需要。

       这在拿过别人的类来做应用的时候很常用的。毕竟不能期待别人给你的接口完全符合你的需要,相信经常给不同设备写应用的同志很有感触吧。

 

       在实际应用中适配器基本有两种实现方法。

1.       基于类的实现

2.       基于对象的实现

 

下面分别来看1个例子

 

基于类的适配器模式实现:

首先看要适配到的接口(或基类,也就是上文例子B的接口)

1.        package com.javapatterns.adapter.classAdapter;

2.         

3.        public interface Target {

4.            byte[] readByte();

5.         

6.            string readString();

7.        }

8.         

9.         

Target接口期待这两个方法,readByte()readString()

 

接着看A实现的类对象:

1.        package com.javapatterns.adapter.classAdapter;

2.         

3.        public class Adaptee {

4.            public byte[] readByte(){...}

5.        }

6.         

Adaptee类只提供了readByte()一个方法,无法满足Target接口的期望。

 

再看C的处理方法:

1.        package com.javapatterns.adapter.classAdapter;

2.         

3.        public class Adapter extends Adaptee implements Target {

4.            public string readString(){

5.                byte[] bytes = readByte();

6.                return byte2String(bytes);

7.            }

8.         

9.            private string byte2String(byte[] bytes){...}

10.     }

11.      

 

他继承了Adaptee类,同时实现Target 接口。这样他自然就拥有了readByte()方法的实现。只需要实现Target接口期望的另一个方法readString()即可。这里用了集成Adaptee的方式,所以说他是基于类的实现。

      

       基于对象的适配器实现:

接口TargetAdaptee类不变,这里不再描述了。来关注下C的实现。

1.        package com.javapatterns.adapter.objectAdapter;

2.         

3.        public class Adapter implements Target {

4.        public Adapter(Adaptee adaptee){

5.                super();

6.                this.adaptee = adaptee;

7.            }

8.         

9.            public byte[] readByte(){

10.             return adaptee.readByte();

11.         }

12.      

13.         public string readString(){

14.             return byte2String(adaptee.readByte());

15.         }

16.      

17.         private Adaptee adaptee;

18.         private string byte2String(byte[] bytes){...}

19.     }

20.      

 

注意看这里C巧妙的利用了一个似有属性 adaptee 来实现Target 所期望的两个方法。这种方式就是基于对象的实现。

 

在实际应用中,很多情况下A提供的方法并不能直接作为B期望的方法的实现,所以基于对象的实现是颇为常用的手段。

 

先说个大家都知道的例子。Javajdbc驱动。其实不同的数据库操作,都有这自己的接口。Jdbc就相当于一个适配器。将Oracle,sqlserver.mysql等操作接口适配成统一的jdbc的数据操作接口。进而方便客户调用。

 

再说一个我实际的例子。我在做发卡程序的时候,需要用到读写射频卡(可以理解为IC卡)的发卡器。不同厂家的发卡起都提供自己的接口。但是我要兼容多家厂商的发卡器啊,所以这里我采取了适配器模式。定义了一个统一的接口,里面包含基本方法(基本就是 init read write 这些基本操作。对于不同品牌发卡器来说,只是接口不同,基本用法都是相同的)然后通过适配器类来将不同品牌的接口适配到我统一的接口上。在通过一个反射工厂来获得具体的适配器类的接口引用。这样我用那个厂家的发卡器,只需要做下配置即可。如果采取了新厂家的发卡器,只需要新增一个适配器实现。很方便吧。

 

最后追加一个C#的例子,是大话设计模式的例子。我想例子多了终归是好的。、

1.        using System;

2.        using System.Collections.Generic;

3.        using System.Text;

4.         

5.        namespace 适配器模式

6.        {

7.            class Program

8.            {

9.                static void  Main (string[] args)

10.             {

11.                 Player b = new Forwards("巴蒂尔");

12.                 b.Attack();

13.      

14.                 Player m = new Guards("麦克格雷迪");

15.                 m.Attack();

16.      

17.                 //Player ym = new Center("姚明");

18.                 Player ym = new Translator("姚明");

19.                 ym.Attack();

20.                 ym.Defense();

21.      

22.                 Console.Read();

23.             }

24.         }

25.      

26.         //篮球运动员

27.         abstract class Player

28.         {

29.             protected string name;

30.             public Player(string name)

31.             {

32.                 this.name = name;

33.             }

34.      

35.             public abstract void Attack();

36.             public abstract void Defense();

37.         }

38.      

39.         //前锋

40.         class Forwards : Player

41.         {

42.             public Forwards(string name)

43.                 : base(name)

44.             {

45.             }

46.      

47.             public override void Attack()

48.             {

49.                 Console.WriteLine("前锋 {0} 进攻", name);

50.             }

51.      

52.             public override void Defense()

53.             {

54.                 Console.WriteLine("前锋 {0} 防守", name);

55.             }

56.         }

57.      

58.         //中锋

59.         class Center : Player

60.         {

61.             public Center(string name)

62.                 : base(name)

63.             {

64.             }

65.      

66.             public override void Attack()

67.             {

68.                 Console.WriteLine("中锋 {0} 进攻", name);

69.             }

70.      

71.             public override void Defense()

72.             {

73.                 Console.WriteLine("中锋 {0} 防守", name);

74.             }

75.         }

76.      

77.         //后卫

78.         class Guards : Player

79.         {

80.             public Guards(string name)

81.                 : base(name)

82.             {

83.             }

84.      

85.             public override void Attack()

86.             {

87.                 Console.WriteLine("后卫 {0} 进攻", name);

88.             }

89.      

90.             public override void Defense()

91.             {

92.                 Console.WriteLine("后卫 {0} 防守", name);

93.             }

94.         }

95.      

96.         //外籍中锋

97.         class ForeignCenter

98.         {

99.             private string name;

100.          public string Name

101.          {

102.              get { return name; }

103.              set { name = value; }

104.          }

105.   

106.          public void 进攻()

107.          {

108.              Console.WriteLine("外籍中锋 {0} 进攻", name);

109.          }

110.   

111.          public void 防守()

112.          {

113.              Console.WriteLine("外籍中锋 {0} 防守", name);

114.          }

115.      }

116.   

117.      //翻译者

118.      class Translator : Player

119.      {

120.          private ForeignCenter wjzf = new ForeignCenter();

121.   

122.          public Translator(string name)

123.              : base(name)

124.          {

125.              wjzf.Name = name;

126.          }

127.   

128.          public override void Attack()

129.          {

130.              wjzf.进攻();

131.          }

132.   

133.          public override void Defense()

134.          {

135.              wjzf.防守();

136.          }

137.      }

138.  }

139.   

 

这里有一个基类Player,包含进攻和防守。不同位置都有不同的实现。但是最终大家都适配到了Player上。

 

       其实现在讲到这里了,大家应该对“开发模式”这个东西有一定了解了。这里重在思想,不重实现。(有点像依赖倒转原则哦)实际应用中很多情况下都是各种模式组合应用。而这个例子打眼一看好像根本都不算适配器模式。但他的思想是把各个位置的人员都适配到Player上面,体现了适配器的思想。所以他可以叫做适配器模式。

 

       其实到这里我实际用过的设计模式就讲得差不多了。再之后的我也是要先学习了。好了,不废话了,学习~

 

       作者:王文斌

       转载请注明出处

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值