模式设计(七)Adapter

       之前我们已经介绍完了创建型模式,它们分别为Factory Method,Abstract Factory,Singleton,Builder,Prototype。创建型模式是创建对象而不是直接实例化对象,这会使程序在判断给定情况下创建哪个对象时更为灵活。在C#中为new,在Pascal中为Create。
       接下来我们要介绍结构型模式,这类模式可以将一组对象组合成更大的结构。对于结构型模式(Structural Pattern)来说主要分为两种组合方式,分别为类模式和对象模式,其主要区别为类模式描述的是如何使用继承提供更有用的程序接口,而对象模式描述的是通过使用对象组合或将对象包含在其他对象里,将对象组合成更大的结构。
       下面我们来看看结构型的第一种模式适配器模式(Adapter Pattern)。
       适配器模式可以将类的接口转变成客户需要的其他接口。这样做的好处就是能很好的复用已有的代码,比如很多公司都生产数据库,如Oracle,IBM,Microsoft,它们的产品各有各的特点,原生的开发方法也有很大的区别,比如Oracle提供OCI接口,Sql Server提供自己专用的API。如果都使用数据库厂商的原生开发方法,那么在Sql Server开发的软件就很难移植到其他的数据库平台上去,这无疑会限制产品的应用范围。为此很多厂商就提供了各种标准的开发接口,比如最早的ODBC,BDE,到现在的ADO.NET等等,有了这种标准的数据库开发接口,我们在一个平台上开发的产品就很容易移植到其他平台上去。
    那么如何让数据库适应不同的标准API而无需大的改动呢,这就是通过适配器模式来实现了,微软最早的ODBC Driver和现在的ADO.NET就相当于一个适配器,可以让数据库适应不同的标准开发接口。这样原有的产品无需针对标准的API做任何改变,只要针对不同的开发API实现一个Dirver就可以了。
       适配器模式的实现原理很简单,就是通过实现了客户指定接口的类来响应客户的请求,然后在适配器内部将请求转发给原有的API接口对应的具有类似功能的方法,然后将处理的结果整理后返回给客户。
        适配器模式有类的适配器模式和对象的适配器模式两种。我们将分别讨论这两种Adapter模式。

     类的Adapter模式的结构:

由图中可以看出,AdapteeXML类没有CreateFile方法,而客户期待这个方法。为了使客户能够使用AdapteeXML类,提供一个中间环节,即类Adapter类,Adapter类实现了ISerTarget接口,此接口中定义了CreateFile方法,并继承自AdapteeXML,Adapter类的CreateFile方法重新封装了AdapteeXMl的CreateXMLFile方法,实现了适配的目的。<?xml:namespace prefix = o />

因为Adapter与AdapteeXML是继承的关系,所以这决定了这个适配器模式是类的。

该适配器模式所涉及的角色包括:

目标(Target)角色:这是客户所期待的接口。因为C#不支持多继承,所以Target必须是接口,不可以是类,这里为ISerTarget。
源(Adaptee)角色:需要适配的类,这里为AdapteeXML。
适配器(Adapter)角色:把源接口转换成目标接口。这一角色必须是类。
以上例子主要是一个XML串行化实例(C#):

 1 None.gif using  System;
 2 None.gif using  System.IO;
 3 None.gif using  System.Xml.Serialization;
 4 None.gif using  System.Xml;
 5 None.gif namespace  AdapterClass
 6 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 7ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
 8InBlock.gif    ///============== Program Description==============
 9InBlock.gif    ///Name:AdapterClass.cs
10InBlock.gif    ///Objective:AdapterClass 
11InBlock.gif    ///Date:2006-05-04 
12InBlock.gif    ///Written By coffee.liu
13InBlock.gif    ///================================================
14ExpandedSubBlockEnd.gif    /// </summary>

15InBlock.gif    class Class1
16ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
17ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
18InBlock.gif        /// 应用程序的主入口点。
19ExpandedSubBlockEnd.gif        /// </summary>

20InBlock.gif        [STAThread]
21InBlock.gif        static void Main(string[] args)
22ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
23InBlock.gif            ISerTarget target=new Adapter();
24InBlock.gif            target.CreateFile();
25InBlock.gif            Console.WriteLine("xml file created");
26ExpandedSubBlockEnd.gif        }

27ExpandedSubBlockEnd.gif    }

28InBlock.gif    [Serializable]
29InBlock.gif    public class Person
30ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
31InBlock.gif        public string Name;
32InBlock.gif        public string Sex;
33InBlock.gif        public DateTime Brith;
34InBlock.gif        private int PersonID;
35InBlock.gif        public Person()
36ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{}
37InBlock.gif        public void SetID(int ID)
38ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{PersonID=ID;}
39ExpandedSubBlockEnd.gif    }

40InBlock.gif
41InBlock.gif    interface ISerTarget
42ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
43InBlock.gif        void CreateFile();
44ExpandedSubBlockEnd.gif    }

45InBlock.gif    class Adapter:AdapteeXML,ISerTarget
46ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
47InBlock.gif        public Adapter():base()
48ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
49ExpandedSubBlockEnd.gif        }

50InBlock.gif
51InBlock.gif        public  void CreateFile()
52ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
53InBlock.gif            this.FillData();
54InBlock.gif            this.CreateXMLFile();
55InBlock.gif      
56ExpandedSubBlockEnd.gif        }

57InBlock.gif    
58ExpandedSubBlockEnd.gif    }

59InBlock.gif    class AdapteeXML
60ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
61InBlock.gif        FileStream aFile;
62InBlock.gif        Person aPerson;
63InBlock.gif        XmlSerializer aXML;
64InBlock.gif        public AdapteeXML()
65ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
66InBlock.gif            aXML=new XmlSerializer(typeof(Person));
67InBlock.gif            aPerson=new Person();
68ExpandedSubBlockEnd.gif        }

69InBlock.gif        public void FillData()
70ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
71InBlock.gif            aPerson.Name="XML";
72InBlock.gif            aPerson.Sex="";
73InBlock.gif            aPerson.Brith=DateTime.Now;
74InBlock.gif            aPerson.SetID(1);
75ExpandedSubBlockEnd.gif        }

76InBlock.gif        public void CreateXMLFile()
77ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
78InBlock.gif            try
79ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
80InBlock.gif                aFile=new FileStream("Person.xml",FileMode.Create);
81ExpandedSubBlockEnd.gif            }

82InBlock.gif            catch(IOException e)
83ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
84InBlock.gif                Console.WriteLine("some error happened!");
85InBlock.gif                Console.WriteLine(e.ToString());
86InBlock.gif                return;
87ExpandedSubBlockEnd.gif            }

88InBlock.gif            aXML.Serialize(aFile,aPerson);
89InBlock.gif            aFile.Close();
90ExpandedSubBlockEnd.gif        }

91ExpandedSubBlockEnd.gif    }

92ExpandedBlockEnd.gif}

93 None.gif
当然用Pascal也可以实现同样的功能,我们看看如何将上面的XML文件读取出来,这里只给出功能性代码,具体扩展希望读者自己思考。
代码(Pascal):
 1 None.gif program AdapterClass;
 2 None.gif   //==============  Program Description ==============
 3 None.gif     // Name:AdapterClass.dpr
 4 None.gif     // Objective:AdapterClass
 5 None.gif     // Date: 2006 - 05 - 04
 6 None.gif     // Written  By  coffee.liu
 7 None.gif     //================================================
 8 None.gif{$APPTYPE CONSOLE}
 9 None.gif
10 None.gifuses
11 None.gif  SysUtils,msxmldom,XMLDoc, oxmldom, xmldom, XMLIntf,windows;
12 None.gif  type ISerTarget = interface
13 None.gif     function  ReadFile():string;
14 None.gif     end ;
15 None.gif  type AdapteeXML = class
16 None.gif      xmlDocument1 :IXMLDocument;
17 None.gif      node:IXMLNode;
18 None.gif       count : Integer ;
19 None.gif      constructor  Create ;
20 None.gif       function  ReadFromXml(Node:IXMLNode; Count : integer ):string;
21 None.gif     end ;
22 None.gif  type Adapter =  class(AdapteeXML,ISerTarget)
23 None.gif    private
24 None.gif     FRefCount :  Integer ;
25 None.gif      public  
26 None.gif     function  QueryInterface(const IID:TGUID;out Obj):HRESULT;stdcall;
27 None.gif     function  _AddRef: Integer ;stdcall;
28 None.gif     function  _Release: Integer ;stdcall; // 这里让接口引用计数器来控制对象生存周期了,这里我为了少写代码没有人为的去控制对象的生存周期,当然读者也可以通过继承TInterfacedObject对象来完成IInterface。     function  ReadFile():string;
29 None.gif    constructor  Create ;
30 None.gif    end ;
31 None.gif
32 None.gif
33 None.gif{ AdapteeXML }
34 None.gif
35 None.gifconstructor AdapteeXML. Create ;
36 None.gif begin
37 None.gif    xmlDocument1 : = TXMLDocument. Create (nil);
38 None.gif    xmlDocument1.LoadFromFile( ' D:\coffee.liu\Delphi7\Projects\Person.xml ' ); // 上面C#例子创建出的XML文件
39 None.gif    XMLDocument1.Active: = true;
40 None.gif     count : = xmlDocument1.ChildNodes. Count ;
41 None.gif    node: =  xmlDocument1.DocumentElement;
42 None.gif end ;
43 None.gif
44 None.gif function  AdapteeXML.ReadFromXml(Node:IXMLNode; Count : integer ):string;
45 None.gif var
46 None.gifi: integer ;
47 None.gif begin
48 None.gif             for  i : =   1   to   Count - 1  do  begin
49 None.gif                 if (node <> nil)  then
50 None.gif                 result: = Node.ChildNodes [ 'Name' ] . Text + ' ; ' + Node.ChildNodes [ 'Sex' ] . Text + ' ; ' + Node.ChildNodes [ 'Brith' ] . Text
51 None.gif
52 None.gif             end ;
53 None.gif            xmlDocument1.Active: = false;
54 None.gif end ;
55 None.gif{ Adapter }
56 None.gif
57 None.gif function  Adapter._AddRef:  Integer ;
58 None.gif begin
59 None.gif   Result : =  InterlockedIncrement(FRefCount);
60 None.gif end ;
61 None.gif
62 None.gif function  Adapter._Release:  Integer ;
63 None.gif begin
64 None.gif   Result : =  InterlockedDecrement(FRefCount);
65 None.gif     if  Result  =   0   then
66 None.gif   Destroy;
67 None.gif end ;
68 None.gif
69 None.gif function  Adapter.QueryInterface(const IID: TGUID; out Obj): HRESULT;
70 None.gif begin
71 None.gif    if  GetInterface(IID, Obj)  then
72 None.gif    Result : =   0
73 None.gif   else
74 None.gif    Result : =  E_NOINTERFACE;
75 None.gif end ;
76 None.gif function  Adapter.ReadFile():string;
77 None.gif begin
78 None.gif   self.ReadFromXml(self.node,self. count );
79 None.gif end ;
80 None.gifconstructor Adapter. Create ;
81 None.gif begin
82 None.gifinherited;
83 None.gif end ;
84 None.gif var
85 None.gifaAdapter:Adapter;
86 None.gif begin
87 None.gif  aAdapter: = Adapter. Create ;
88 None.gif  Writeln(aAdapter.ReadFile);
89 None.gif end .
90 None.gif
     
        对象的Adapter模式的结构:
11.gif
WebResource.axd?d=pLXXeGbWF7eXU8SMs2-GFZvUWY2JNH05dFx5YzJhGUYAYJAFEaTEq36NAhTPy7_KekvzDFwt8wvQWdByvJIGWdEq6x2KpKD80&t=632785713320000000
 

从图中可以看出:客户端需要调用CreateFile方法,而AdapteeXML,AdapteeSoap,AdapteeBin没有该方法,为了使客户端能够使用AdapteeXXX类,需要提供一个包装(Wrapper)类Adapter。这个包装类包装AdapteeXXX的实例,从而将客户端与AdapteeXXX衔接起来。
由于Adapter与AdapteeXXX是委派关系,这决定了这个适配器模式是对象的。

该适配器模式所涉及的角色包括:

目标(Target)角色:这是客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口,这里为ISerTarget接口。
源(Adaptee)角色:需要适配的类,这里为AdapteeXML,AdapteeSoap,AdapteeBin类。
适配器(Adapter)角色:通过在内部包装(Wrap)Adaptee对象,把源接口转换成目标接口。

以上的例子主要为将Person类串行化为不同的形式的例子,这里分别保存为xml,soap,binary形式。由于我们使用了Adapter进行了统一封装,这样用户可以不必知道具体的封装细节,运用统一的CreateFile方法即可将Person类串行化为不同的形式。
具体代码(C#):

  1 None.gif using  System;
  2 None.gif using  System.IO;
  3 None.gif using  System.Xml.Serialization;
  4 None.gif using  System.Xml;
  5 None.gif using  System.Runtime.Serialization.Formatters.Binary;
  6 ExpandedBlockStart.gifContractedBlock.gif /**/ /////运行时要将System.Runtime.Serialization.Formatters.Soap.dll的引用添加到项目中
  7 None.gif using  System.Runtime.Serialization.Formatters.Soap;
  8 None.gif
  9 None.gif namespace  AdapterObject
 10 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
 11ExpandedSubBlockStart.gifContractedSubBlock.gif    /**//// <summary>
 12InBlock.gif    ///============== Program Description==============
 13InBlock.gif    ///Name:AdapterObject.cs
 14InBlock.gif    ///Objective:AdapterObject 
 15InBlock.gif    ///Date:2006-05-04 
 16InBlock.gif    ///Written By coffee.liu
 17InBlock.gif    ///================================================
 18ExpandedSubBlockEnd.gif    /// </summary>

 19InBlock.gif    class Class1
 20ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
 21InBlock.gif        [STAThread]
 22InBlock.gif        static void Main(string[] args)
 23ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
 24InBlock.gif            ISerTarget target=new Adapter("XML");
 25InBlock.gif            target.CreateFile();
 26InBlock.gif            Console.WriteLine("XML file created");
 27InBlock.gif
 28InBlock.gif            target=new Adapter("Soap");
 29InBlock.gif            target.CreateFile();
 30InBlock.gif            Console.WriteLine("Soap file created");
 31InBlock.gif
 32InBlock.gif            target=new Adapter("Bin");
 33InBlock.gif            target.CreateFile();
 34InBlock.gif            Console.WriteLine("Bin file created");
 35ExpandedSubBlockEnd.gif        }

 36ExpandedSubBlockEnd.gif    }

 37InBlock.gif    [Serializable]
 38ExpandedSubBlockStart.gifContractedSubBlock.gif    public class Persondot.gif{
 39InBlock.gif        public string Name;
 40InBlock.gif        public string Sex;
 41InBlock.gif        public DateTime Brith;
 42InBlock.gif        private int PersonID;
 43InBlock.gif        public Person()
 44ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{}
 45InBlock.gif        public void SetID(int ID)
 46ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{PersonID=ID;}
 47ExpandedSubBlockEnd.gif    }

 48InBlock.gif
 49ExpandedSubBlockStart.gifContractedSubBlock.gif    interface ISerTargetdot.gif{
 50InBlock.gif        void CreateFile();
 51ExpandedSubBlockEnd.gif    }

 52ExpandedSubBlockStart.gifContractedSubBlock.gif    class Adapter:ISerTargetdot.gif{
 53InBlock.gif       private AdapteeXML aXML;
 54InBlock.gif       private AdapteeSoap aSoap;
 55InBlock.gif       private AdapteeBin aBin;
 56InBlock.gif       private string S;
 57ExpandedSubBlockStart.gifContractedSubBlock.gif        public Adapter(string s)dot.gif{
 58InBlock.gif            S=s;
 59InBlock.gif            if (s=="XML")
 60ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 61InBlock.gif                aXML=new AdapteeXML();
 62InBlock.gif                aXML.FillData();
 63ExpandedSubBlockEnd.gif            }

 64InBlock.gif            else
 65InBlock.gif                if (s=="Soap")
 66ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 67InBlock.gif                aSoap=new AdapteeSoap();
 68InBlock.gif                aSoap.FillData();
 69ExpandedSubBlockEnd.gif            }

 70InBlock.gif            else if (s=="Bin")
 71ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 72InBlock.gif                aBin=new AdapteeBin();
 73InBlock.gif                aBin.FillData();
 74ExpandedSubBlockEnd.gif            }

 75InBlock.gif            else
 76ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
 77InBlock.gif                aXML=new AdapteeXML();
 78InBlock.gif                aXML.FillData();
 79ExpandedSubBlockEnd.gif            }

 80ExpandedSubBlockEnd.gif        }

 81InBlock.gif
 82ExpandedSubBlockStart.gifContractedSubBlock.gif      public  void CreateFile()dot.gif{
 83InBlock.gif          if (S=="XML")
 84ExpandedSubBlockStart.gifContractedSubBlock.gif          dot.gif{
 85InBlock.gif              aXML.CreateXMLFile();
 86ExpandedSubBlockEnd.gif          }

 87InBlock.gif          else
 88InBlock.gif              if (S=="Soap")
 89ExpandedSubBlockStart.gifContractedSubBlock.gif          dot.gif{
 90InBlock.gif              aSoap.CreateSoapFile();
 91ExpandedSubBlockEnd.gif          }

 92InBlock.gif          else if (S=="Bin")
 93ExpandedSubBlockStart.gifContractedSubBlock.gif          dot.gif{
 94InBlock.gif              aBin.CreateBinFile();
 95ExpandedSubBlockEnd.gif          }

 96InBlock.gif          else
 97ExpandedSubBlockStart.gifContractedSubBlock.gif          dot.gif{
 98InBlock.gif              aXML.CreateXMLFile();
 99ExpandedSubBlockEnd.gif          }
 
100InBlock.gif      
101ExpandedSubBlockEnd.gif      }

102InBlock.gif    
103ExpandedSubBlockEnd.gif    }

104ExpandedSubBlockStart.gifContractedSubBlock.gif    class AdapteeSoapdot.gif{
105InBlock.gif      FileStream aFileSoap;
106InBlock.gif        Person aPerson;
107InBlock.gif        SoapFormatter aSoapFormatter;
108ExpandedSubBlockStart.gifContractedSubBlock.gif        public AdapteeSoap()dot.gif{
109InBlock.gif          aSoapFormatter=new SoapFormatter();
110InBlock.gif            aPerson=new Person();
111ExpandedSubBlockEnd.gif        }

112InBlock.gif        public void FillData()
113ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
114InBlock.gif            aPerson.Name="Soap";
115InBlock.gif            aPerson.Sex="";
116InBlock.gif            aPerson.Brith=DateTime.Now;
117InBlock.gif            aPerson.SetID(2);
118ExpandedSubBlockEnd.gif        }

119ExpandedSubBlockStart.gifContractedSubBlock.gif        public void CreateSoapFile()dot.gif{
120InBlock.gif            try
121ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
122InBlock.gif                aFileSoap=new FileStream("SoapPerson.xml",FileMode.OpenOrCreate);
123InBlock.gif                aSoapFormatter.Serialize(aFileSoap,aPerson);
124InBlock.gif                aFileSoap.Close();
125ExpandedSubBlockEnd.gif            }

126ExpandedSubBlockStart.gifContractedSubBlock.gif            catch(IOException e)dot.gif{
127InBlock.gif              Console.WriteLine("some error happened");
128InBlock.gif                Console.WriteLine(e.ToString());
129InBlock.gif                return;
130ExpandedSubBlockEnd.gif            }

131InBlock.gif
132ExpandedSubBlockEnd.gif        }

133ExpandedSubBlockEnd.gif    }

134InBlock.gif    class AdapteeBin
135ExpandedSubBlockStart.gifContractedSubBlock.gif    dot.gif{
136InBlock.gif        FileStream aFileBin;
137InBlock.gif        Person aPerson;
138InBlock.gif        BinaryFormatter aBinaryFormatter;
139InBlock.gif        public AdapteeBin()
140ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
141InBlock.gif            aBinaryFormatter=new BinaryFormatter();
142InBlock.gif            aPerson=new Person();
143ExpandedSubBlockEnd.gif        }

144InBlock.gif        public void FillData()
145ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
146InBlock.gif            aPerson.Name="Bin";
147InBlock.gif            aPerson.Sex="";
148InBlock.gif            aPerson.Brith=DateTime.Now;
149InBlock.gif            aPerson.SetID(3);
150ExpandedSubBlockEnd.gif        }

151InBlock.gif        public void CreateBinFile()
152ExpandedSubBlockStart.gifContractedSubBlock.gif        dot.gif{
153InBlock.gif            try
154ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
155InBlock.gif                aFileBin=new FileStream("BinPerson.data",FileMode.OpenOrCreate);
156InBlock.gif                aBinaryFormatter.Serialize(aFileBin,aPerson);
157InBlock.gif                aFileBin.Close();
158ExpandedSubBlockEnd.gif            }

159InBlock.gif            catch(IOException e)
160ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
161InBlock.gif                Console.WriteLine("some error happened");
162InBlock.gif                Console.WriteLine(e.ToString());
163InBlock.gif                return;
164ExpandedSubBlockEnd.gif            }

165InBlock.gif
166ExpandedSubBlockEnd.gif        }

167ExpandedSubBlockEnd.gif    }

168ExpandedSubBlockStart.gifContractedSubBlock.gif    class AdapteeXMLdot.gif{
169InBlock.gif        FileStream aFile;
170InBlock.gif        Person aPerson;
171InBlock.gif        XmlSerializer aXML;
172ExpandedSubBlockStart.gifContractedSubBlock.gif        public AdapteeXML()dot.gif{
173InBlock.gif         aXML=new XmlSerializer(typeof(Person));
174InBlock.gif            aPerson=new Person();
175ExpandedSubBlockEnd.gif    }

176ExpandedSubBlockStart.gifContractedSubBlock.gif        public void FillData()dot.gif{
177InBlock.gif        aPerson.Name="XML";
178InBlock.gif            aPerson.Sex="";
179InBlock.gif            aPerson.Brith=DateTime.Now;
180InBlock.gif            aPerson.SetID(1);
181ExpandedSubBlockEnd.gif        }

182ExpandedSubBlockStart.gifContractedSubBlock.gif        public void CreateXMLFile()dot.gif{
183InBlock.gif            try
184ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
185InBlock.gif                aFile=new FileStream("Person.xml",FileMode.Create);
186ExpandedSubBlockEnd.gif            }

187InBlock.gif            catch(IOException e)
188ExpandedSubBlockStart.gifContractedSubBlock.gif            dot.gif{
189InBlock.gif             Console.WriteLine("some error happened!");
190InBlock.gif                Console.WriteLine(e.ToString());
191InBlock.gif                return;
192ExpandedSubBlockEnd.gif            }

193InBlock.gif            aXML.Serialize(aFile,aPerson);
194InBlock.gif            aFile.Close();
195ExpandedSubBlockEnd.gif        }

196ExpandedSubBlockEnd.gif    }

197ExpandedBlockEnd.gif}

198 None.gif

类适配器和对象适配器之间的差别:
   1.当我们想匹配一个类和它所有子类时,类适配器将不能胜任,因为在创建子类时就已定义了派生它的基类。如上第二例,要想改为类适配器模式就必须使用三个Adapter来分别封装三个Adaptee,这样做不太实际。
   2.类适配器允许适配器更改某些被匹配的类的方法,同时还允许使用其他未修改的方法。
   3. 对象适配器通过将子类传递给构造函数而允许匹配所有子类,如上面的第二例。
   4.对象适配器要求读者将希望使用的,被匹配对象的方法提到表面上来。

转载于:https://www.cnblogs.com/coffeeliu/archive/2006/05/04/391410.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值