Adapter模式
同样的方法我们来解决中国人和英国人对话的问题:
概述
Adapter模式又叫适配器(变压器)模式:把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口原因不匹配而无法一起工作的两个类能够一起工作。适配类可以根据参数返还一个合适的实例给客户端。
设计
那么是如何“适配”的呢?比如,东西A想使用东西B,但是A无法使用B,怎么办?A就让东西C帮忙,A通过C就可以用B了。其实A、B就好像是两节水管,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
32
namespace 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
// Adapter2

3
// Intent: "Convert the interface of a class into another interface 4
// clients expect. Adapter lets classes work together that couldn't5
// otherwise because of incompatible interfaces". 6

7
// For further information, read "Design Patterns", p139, Gamma et al.,8
// Addison-Wesley, ISBN:0-201-63361-29

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 object18
* 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 code26
* (in GenericClientCode) is written to expect a class called FrameworkXTarget.27
* To solve the probelm we create an Adapter class, which it a FrameworkXTarget28
* to the client, and calls FrameworkYAdaptee.29
* 30
*/31
32
namespace Adapter_DesignPattern33
{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 FrameworkYAdaptee45
{46
public void QuiteADifferentRequest(string str) 47
{48
Console.WriteLine("QuiteADifferentRequest = {0}", str);49
} 50
}51

52
class OurAdapter : FrameworkXTarget53
{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 Client67
{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 here74
// 
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

示例代码为:
1
using System;
2
3
namespace 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
using System;2

3
namespace Example4
{5
/// <summary>6
/// 示例7
/// </summary>8
class Example9
{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 Water24
{25
public Water() {}26
}27
/// <summary>28
/// 大水管29
/// </summary>30
/// <remarks>31
/// 程序员A编写32
/// 测试员C测试33
/// </remarks>34
public class BigPipe35
{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 Hosepipe50
{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 : Hosepipe65
{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
#endregion80
}81
/// <summary>82
/// 中水管83
/// </summary>84
public class MiddleHosepipe : Hosepipe85
{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
#endregion100
}101
/// <summary>102
/// 大水管103
/// </summary>104
/// <remarks>105
/// 当准备写大水管的进出水方法时,发现程序A已经写过同样功能的代码106
/// 但是A命名时并没有征求你的意见以及你也没有要求107
/// 所以只要采用Adapter模式,使用A已编好的功能108
/// </remarks>109
public class BigHosepipe : Hosepipe110
{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
#endregion122
}123
}124
}125

同样的方法我们来解决中国人和英国人对话的问题:
1
namespace 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
}
namespace DesignPattern.Template2
{3
/// <summary>4
/// 人们的话语5
/// </summary>6
public class Words7
{8
public Words(){}9
}10
/// <summary>11
/// 英国人12
/// </summary>13
public class English14
{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 Chinese32
{33
public Chinese()34
{35
}36
public string Speak()37
{38
39
get40
{41
return words; 42
}43
}44
public Words Understand(Words words )45
{46
return newWords;47
}48
} 49
50
public class LanguageAdapter:English51
{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
}

