Adapter模式

      概述

Adapter模式又叫适配器(变压器)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。

     设计

那么是如何“适配”的呢?比如,东西A想使用东西B,但是A无法使用B,怎么办?A就让东西C帮忙,A通过C就可以用B了。其实AB就好像是两节水管,C就好像是连接水管的接头。

     实现

UML图:

 标准示例:

 1// Adapter
 2
 3// Intent: "Convert the interface of a class into another interface 
 4// clients expect. Adapter lets classes work together that couldn't
 5// otherwise because of incompatible interfaces". 
 6
 7// For further information, read "Design Patterns", p139, Gamma et al.,
 8// Addison-Wesley, ISBN:0-201-63361-2
 9
10/* Notes:
11 * Adapters are often used when client code is written to expect classes 
12 * from one framework, and it meant to work with classes from a totally 
13 * different framework. Assume you cannot change the code of either framework. 
14 * the solution is for you to write an adapter, which appears like a 
15 * native class to each framework.  
16 * 
17 * There are two different types of adapters - class adapter and object
18 * adapter. Class adapters are based on multiple inheritance - specifically 
19 * the interface of the target class and the implementation of the adaptee. 
20 * Unfortunately C# supports multiple inheritance for interfaces but not 
21 * for classes. Object adapters derive from the target (single inheritance)
22 * and maintain a private instance of the adoptee. 
23 * 
24 * The sample code here shows an object adapter. We have a class called 
25 * FrameworkYAdaptee which we wish to use, yet the (bulk of) the client code
26 * (in GenericClientCode) is written to expect a class called FrameworkXTarget.
27 * To solve the probelm we create an Adapter class, which it a FrameworkXTarget
28 * to the client, and calls FrameworkYAdaptee.
29 * 
30 */

31 
32namespace Adapter_DesignPattern
33{
34    using System;
35
36    class FrameworkXTarget 
37    {
38        virtual public void SomeRequest(int x)
39        {
40            // normal implementation of SomeRequest goes here                    
41        }

42    }

43
44    class FrameworkYAdaptee
45    {
46        public void QuiteADifferentRequest(string str) 
47        {
48            Console.WriteLine("QuiteADifferentRequest = {0}", str);
49        }
        
50    }

51
52    class OurAdapter : FrameworkXTarget
53    {
54        private FrameworkYAdaptee adaptee = new FrameworkYAdaptee();
55        override public void SomeRequest(int a)
56        {
57            string b;
58            b = a.ToString();
59            adaptee.QuiteADifferentRequest(b);
60        }
        
61    }

62
63    /// <summary>
64    ///    Summary description for Client.
65    /// </summary>

66    public class Client
67    {
68        void GenericClientCode(FrameworkXTarget x)
69        {
70            // We assume this function contains client-side code that only 
71            // knows about FrameworkXTarget.
72            x.SomeRequest(4);
73            // other calls to FrameworkX go here
74            // 
75        }

76        
77        public static int Main(string[] args)
78        {
79            Client c = new Client();
80            FrameworkXTarget x = new OurAdapter();
81            c.GenericClientCode(x);    
82            return 0;
83        }

84    }

85}

86
87


示例代码为:

  1using System;
  2
  3namespace Example
  4{
  5    /// <summary>
  6    /// 示例
  7    /// </summary>

  8    class Example
  9    {
 10        /// <summary>
 11        /// 应用程序的主入口点。
 12        /// </summary>

 13        [STAThread]
 14        static void Main(string[] args)
 15        {
 16            Hosepipe pipe = new BigHosepipe() ;
 17            pipe.Influx() ;
 18            pipe.Effuse() ;
 19        }

 20        /// <summary>
 21        /// 水
 22        /// </summary>

 23        public class Water
 24        {
 25            public Water() {}
 26        }

 27        /// <summary>
 28        /// 大水管
 29        /// </summary>
 30        /// <remarks>
 31        /// 程序员A编写
 32        /// 测试员C测试
 33        /// </remarks>

 34        public class BigPipe
 35        {
 36            public Water In() 
 37            {
 38                Console.WriteLine( "流入水" ) ;
 39                return new Water() ;
 40            }
 
 41            public void Out() 
 42            {
 43                Console.WriteLine( "水流出" ) ;
 44            }

 45        }

 46        /// <summary>
 47        /// 水管接口
 48        /// </summary>

 49        interface Hosepipe
 50        {
 51            /// <summary>
 52            /// 进水
 53            /// </summary>
 54            /// <returns></returns>

 55            Water Influx() ;
 56            /// <summary>
 57            /// 出水
 58            /// </summary>

 59            void Effuse() ;
 60        }

 61        /// <summary>
 62        /// 小水管
 63        /// </summary>

 64        public class SmallHosepipe : Hosepipe
 65        {
 66            #region Hosepipe 成员
 67
 68            public Water Influx()
 69            {
 70                // TODO:  添加 SmallHosepipe.Influx 实现
 71                return null;
 72            }

 73
 74            public void Effuse()
 75            {
 76                // TODO:  添加 SmallHosepipe.Effuse 实现
 77            }

 78
 79            #endregion

 80        }

 81        /// <summary>
 82        /// 中水管
 83        /// </summary>

 84        public class MiddleHosepipe : Hosepipe
 85        {
 86            #region Hosepipe 成员
 87
 88            public Water Influx()
 89            {
 90                // TODO:  添加 MiddleHosepipe.Influx 实现
 91                return null;
 92            }

 93
 94            public void Effuse()
 95            {
 96                // TODO:  添加 MiddleHosepipe.Effuse 实现
 97            }

 98
 99            #endregion

100        }

101        /// <summary>
102        /// 大水管
103        /// </summary>
104        /// <remarks>
105        /// 当准备写大水管的进出水方法时,发现程序A已经写过同样功能的代码
106        /// 但是A命名时并没有征求你的意见以及你也没有要求
107        /// 所以只要采用Adapter模式,使用A已编好的功能
108        /// </remarks>

109        public class BigHosepipe : Hosepipe
110        {
111            private BigPipe bigPipe = new BigPipe() ;
112            #region Hosepipe 成员
113            public Water Influx()
114            {
115                return bigPipe.In() ;
116            }

117            public void Effuse()
118            {
119                bigPipe.Out() ;
120            }

121            #endregion

122        }

123    }

124}

125


同样的方法我们来解决中国人和英国人对话的问题:
 1namespace DesignPattern.Template
 2{
 3    /// <summary>
 4    /// 人们的话语
 5    /// </summary>

 6    public class Words
 7    {
 8        public Words(){}
 9    }

10    /// <summary>
11    /// 英国人
12    /// </summary>

13    public class English
14    {
15        public English()
16        {
17        }

18        public Words Speak()
19        {
20                return words; 
21        }

22        public Words Understand(Words words )
23        {
24            return newWords;
25        }

26    }

27    
28    /// <summary>
29    /// 中国人
30    /// </summary>

31    public class Chinese
32    {
33        public Chinese()
34        {
35        }

36        public string Speak()
37        {
38            
39            get
40            {
41                return words; 
42            }

43        }

44        public Words Understand(Words words )
45        {
46            return newWords;
47        }

48    }
  
49    
50    public class LanguageAdapter:English
51    {
52     private English english=new English ();
53     /// <summary>
54     /// 这个函数实现了英文转化中文
55     /// </summary>
56     /// <param name="words"></param>
57     /// <returns></returns>

58     public Words Translate(Word words)
59     {
60     }

61     /// <summary>
62     /// 重载了英国人说话的方法
63     /// </summary>
64     /// <returns></returns>

65     public Words Speak()
66     {
67         Words englishWords= english.Speak ();
68         return this.Translate(englishWords);
69     }

70     public Words Understand( Words words)
71     {
72         Words englishWords=english.Understand (words);
73         return this.Translate (englishWords);
74     }

75    }

76}